Repository: metal3-io/baremetal-operator
Pull request #1551 (2024-02-12 13:07:36)

🌱 Add 'wait-power-state' interval to fixture test for flake fix
**What this PR does / why we need it**:
 Add the interval 'wait-power-state' to our fixture test to fix a flake. 

metal3-io-bot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
**Once this PR has been reviewed and has the lgtm label**, please assign [andfasano](https://github.com/andfasano) for approval. For more information see [the Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=metal3-io%2Fbaremetal-operator).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/metal3-io/baremetal-operator/blob/main/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["andfasano"]} -->
maxrantil: /metal3-bmo-e2e-test-pull
/test-centos-e2e-integration-main

Patch:
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 8fbebf20..f0a4a03e 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -27,7 +27,7 @@ jobs:
     - name: Install go
       uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
       with:
-        go-version: '1.21'
+        go-version: '1.20'
     - name: Generate release notes
       run: |
         make release-notes
diff --git a/.golangci.yaml b/.golangci.yaml
index 4d495655..19aaf51d 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -1,168 +1,160 @@
 run:
   deadline: 5m
   skip-dirs:
-  - mock*
+    - mock*
   skip-files:
-  - "zz_generated.*\\.go$"
-  - ".*conversion.*\\.go$"
+    - "zz_generated.*\\.go$"
+    - ".*conversion.*\\.go$"
 linters:
   disable-all: true
   enable:
-  - asciicheck
-  - bodyclose
-  - dogsled
-  # - errcheck
-  # - errorlint
-  - exportloopref
-  - goconst
-  - gocritic
-  - godot
-  - gofmt
-  - goimports
-  - gosimple
-  - govet
-  - importas
-  - gosec
-  - ineffassign
-  - misspell
-  # - nakedret
-  # - nilerr
-  # - noctx
-  - nolintlint
-  - prealloc
-  - predeclared
-  - revive
-  - rowserrcheck
-  - staticcheck
-  - stylecheck
-  - thelper
-  - typecheck
-  - unconvert
-  - unused
-  - whitespace
+    - asciicheck
+    - bodyclose
+    - dogsled
+    # - errcheck
+    # - errorlint
+    - exportloopref
+    # - goconst
+    # - gocritic
+    # - godot
+    # - gofmt
+    # - goimports
+    # - gosimple
+    # - govet
+    # - importas
+    # - gosec
+    # - ineffassign
+    # - misspell
+    # - nakedret
+    # - nilerr
+    # - noctx
+    # - nolintlint
+    # - prealloc
+    # - predeclared
+    # - revive
+    # - rowserrcheck
+    # - staticcheck
+    # - stylecheck
+    # - thelper
+    # - typecheck
+    # - unconvert
+    # - unused
+    # - whitespace
   # Run with --fast=false for more extensive checks
   fast: true
 
 linters-settings:
   gosec:
-    go: "1.21"
+    go: "1.20"
     severity: medium
     confidence: medium
     concurrency: 8
   importas:
     no-unaliased: true
     alias:
-    # Kubernetes
-    - pkg: k8s.io/api/core/v1
-      alias: corev1
-    - pkg: k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
-      alias: apiextensionsv1
-    - pkg: k8s.io/apimachinery/pkg/apis/meta/v1
-      alias: metav1
-    - pkg: k8s.io/apimachinery/pkg/api/errors
-      alias: k8serrors
-    - pkg: k8s.io/apimachinery/pkg/util/errors
-      alias: kerrors
-    - pkg: k8s.io/component-base/logs/api/v1
-      alias: logsv1
-    # Controller Runtime
-    - pkg: sigs.k8s.io/controller-runtime
-      alias: ctrl
-    # BMO
-    - pkg: github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1
-      alias: metal3api
+      # Kubernetes
+      - pkg: k8s.io/api/core/v1
+        alias: corev1
+      - pkg: k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
+        alias: apiextensionsv1
+      - pkg: k8s.io/apimachinery/pkg/apis/meta/v1
+        alias: metav1
+      - pkg: k8s.io/apimachinery/pkg/api/errors
+        alias: k8serrors
+      - pkg: k8s.io/apimachinery/pkg/util/errors
+        alias: kerrors
+      - pkg: k8s.io/component-base/logs/api/v1
+        alias: logsv1
+      # Controller Runtime
+      - pkg: sigs.k8s.io/controller-runtime
+        alias: ctrl
+      # BMO
+      - pkg: github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1
+        alias: metal3api
   nolintlint:
     allow-unused: false
     allow-leading-space: false
     require-specific: true
   staticcheck:
-    go: "1.21"
+    go: "1.20"
   stylecheck:
-    go: "1.21"
+    go: "1.20"
   gocritic:
     enabled-tags:
-    - experimental
+      - experimental
     disabled-checks:
-    - appendAssign
-    - dupImport # https://github.com/go-critic/go-critic/issues/845
-    - evalOrder
-    - ifElseChain
-    - octalLiteral
-    - regexpSimplify
-    - sloppyReassign
-    - truncateCmp
-    - typeDefFirst
-    - unnamedResult
-    - unnecessaryDefer
-    - whyNoLint
-    - wrapperFunc
+      - appendAssign
+      - dupImport # https://github.com/go-critic/go-critic/issues/845
+      - evalOrder
+      - ifElseChain
+      - octalLiteral
+      - regexpSimplify
+      - sloppyReassign
+      - truncateCmp
+      - typeDefFirst
+      - unnamedResult
+      - unnecessaryDefer
+      - whyNoLint
+      - wrapperFunc
   unused:
-    go: "1.21"
+    go: "1.20"
 issues:
   exclude-rules:
-  - path: test/e2e
-    linters:
-    - gosec
-  - path: test/e2e
-    linters:
-    - goconst
-  - path: _test\.go
-    linters:
-    - goconst
-  - path: _test\.go
-    linters:
-    - unused
-    - revive
-    - stylecheck
-  # Specific exclude rules for deprecated fields that are still part of the codebase.
-  # These should be removed as the referenced deprecated item is removed from the project.
-  - linters:
-    - staticcheck
-    text: "SA1019:"
-  # Disable linters for conversion
-  - linters:
-    - staticcheck
-    text: "SA1019:"
-    path: .*(api|types)\/.*\/conversion.*\.go$
-  # Dot imports for gomega or ginkgo are allowed
-  # within test files.
-  - path: _test\.go
-    text: should not use dot imports
-  - path: (test|e2e)/.*.go
-    text: should not use dot imports
-  - linters:
-    - revive
-    text: "exported: exported method .*\\.(Reconcile|SetupWithManager|SetupWebhookWithManager) should have comment or be unexported"
-  # Exclude some packages or code to require comments, for example test code, or fake clients.
-  - linters:
-    - revive
-    text: exported (method|function|type|const) (.+) should have comment or be unexported
-    source: (func|type).*Fake.*
-  - linters:
-    - revive
-    text: exported (method|function|type|const) (.+) should have comment or be unexported
-    path: fake_\.go
-  - linters:
-    - revive
-    text: exported (method|function|type|const) (.+) should have comment or be unexported
-    path: .*(api|types)\/.*\/conversion.*\.go$
-  - linters:
-    - revive
-    text: "var-naming: don't use underscores in Go names;"
-    path: .*(api|types)\/.*\/conversion.*\.go$
-  - linters:
-    - revive
-    text: "receiver-naming: receiver name"
-    path: .*(api|types)\/.*\/conversion.*\.go$
-  - linters:
-    - stylecheck
-    text: "ST1003: should not use underscores in Go names;"
-    path: .*(api|types)\/.*\/conversion.*\.go$
-  - linters:
-    - stylecheck
-    text: "ST1016: methods on the same type should have the same receiver name"
-    path: .*(api|types)\/.*\/conversion.*\.go$
+    - path: test/e2e
+      linters:
+        - gosec
+    - path: _test\.go
+      linters:
+        - unused
+    # Specific exclude rules for deprecated fields that are still part of the codebase.
+    # These should be removed as the referenced deprecated item is removed from the project.
+    - linters:
+        - staticcheck
+      text: "SA1019:"
+    # Disable linters for conversion
+    - linters:
+        - staticcheck
+      text: "SA1019:"
+      path: .*(api|types)\/.*\/conversion.*\.go$
+    # Dot imports for gomega or ginkgo are allowed
+    # within test files.
+    - path: _test\.go
+      text: should not use dot imports
+    - path: (test|e2e)/.*.go
+      text: should not use dot imports
+    - linters:
+        - revive
+      text: "exported: exported method .*\\.(Reconcile|SetupWithManager|SetupWebhookWithManager) should have comment or be unexported"
+    # Exclude some packages or code to require comments, for example test code, or fake clients.
+    - linters:
+        - revive
+      text: exported (method|function|type|const) (.+) should have comment or be unexported
+      source: (func|type).*Fake.*
+    - linters:
+        - revive
+      text: exported (method|function|type|const) (.+) should have comment or be unexported
+      path: fake_\.go
+    - linters:
+        - revive
+      text: exported (method|function|type|const) (.+) should have comment or be unexported
+      path: .*(api|types)\/.*\/conversion.*\.go$
+    - linters:
+        - revive
+      text: "var-naming: don't use underscores in Go names;"
+      path: .*(api|types)\/.*\/conversion.*\.go$
+    - linters:
+        - revive
+      text: "receiver-naming: receiver name"
+      path: .*(api|types)\/.*\/conversion.*\.go$
+    - linters:
+        - stylecheck
+      text: "ST1003: should not use underscores in Go names;"
+      path: .*(api|types)\/.*\/conversion.*\.go$
+    - linters:
+        - stylecheck
+      text: "ST1016: methods on the same type should have the same receiver name"
+      path: .*(api|types)\/.*\/conversion.*\.go$
   include:
-  - EXC0002 # include "missing comments" issues from golangci-lint
+    - EXC0002 # include "missing comments" issues from golangci-lint
   max-issues-per-linter: 0
   max-same-issues: 0
diff --git a/Dockerfile b/Dockerfile
index 5825ff5b..ed2672c2 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
 # Support FROM override
-ARG BUILD_IMAGE=docker.io/golang:1.21.6@sha256:76aadd914a29a2ee7a6b0f3389bb2fdb87727291d688e1d972abe6c0fa6f2ee0
+ARG BUILD_IMAGE=docker.io/golang:1.20.12@sha256:685846c2eb68f6ae4d784d56125ea9894981b3408340aa7d89362fef83e1aebb
 ARG BASE_IMAGE=gcr.io/distroless/static:nonroot@sha256:9ecc53c269509f63c69a266168e4a687c7eb8c0cfd753bd8bfcaa4f58a90876f
 
 # Build the manager binary
diff --git a/Makefile b/Makefile
index 5bbc77fb..ac274797 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ RUN_NAMESPACE = metal3
 GO_TEST_FLAGS = $(TEST_FLAGS)
 DEBUG = --debug
 COVER_PROFILE = cover.out
-GO_VERSION ?= 1.21.6
+GO_VERSION ?= 1.20.12
 
 ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
 
@@ -139,9 +139,8 @@ $(GOLANGCI_LINT_BIN): $(GOLANGCI_LINT) ## Build a local copy of golangci-lint.
 .PHONY: lint
 lint: $(GOLANGCI_LINT)
 	$(GOLANGCI_LINT) run -v ./...
-	cd apis; $(GOLANGCI_LINT) run -v ./...
-	cd test; $(GOLANGCI_LINT) run -v ./...
-	cd pkg/hardwareutils; $(GOLANGCI_LINT) run -v ./...
+	cd test; $(GOLANGCI_LINT) run -v
+	cd pkg/hardwareutils; $(GOLANGCI_LINT) run -v
 
 .PHONY: manifest-lint
 manifest-lint: ## Run manifest validation
diff --git a/Tiltfile b/Tiltfile
index 1ba1ee53..1e94d2bf 100644
--- a/Tiltfile
+++ b/Tiltfile
@@ -61,7 +61,7 @@ def validate_auth():
 
 tilt_helper_dockerfile_header = """
 # Tilt image
-FROM golang:1.21 as tilt-helper
+FROM golang:1.20 as tilt-helper
 # Support live reloading with Tilt
 RUN wget --output-document /restart.sh --quiet https://raw.githubusercontent.com/windmilleng/rerun-process-wrapper/master/restart.sh  && \
     wget --output-document /start.sh --quiet https://raw.githubusercontent.com/windmilleng/rerun-process-wrapper/master/start.sh && \
diff --git a/apis/go.mod b/apis/go.mod
index 1e793b6a..95b262e7 100644
--- a/apis/go.mod
+++ b/apis/go.mod
@@ -1,6 +1,6 @@
 module github.com/metal3-io/baremetal-operator/apis
 
-go 1.21
+go 1.20
 
 require (
 	github.com/google/uuid v1.6.0
diff --git a/apis/go.sum b/apis/go.sum
index 98de0064..6792de1d 100644
--- a/apis/go.sum
+++ b/apis/go.sum
@@ -9,12 +9,10 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
 github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
 github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
-github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
 github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo=
-github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA=
 github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
 github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
 github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
@@ -22,11 +20,9 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En
 github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
 github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
 github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
-github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 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=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
@@ -41,7 +37,6 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
 github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
 github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
-github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -52,7 +47,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
-github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -69,9 +63,7 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
-github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
 github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
-github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -85,9 +77,7 @@ github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO
 github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
 github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
 github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
-github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -100,9 +90,7 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
-go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
 go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
-go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -142,7 +130,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
-golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/apis/metal3.io/v1alpha1/baremetalhost_types.go b/apis/metal3.io/v1alpha1/baremetalhost_types.go
index 08c05d10..af629b64 100644
--- a/apis/metal3.io/v1alpha1/baremetalhost_types.go
+++ b/apis/metal3.io/v1alpha1/baremetalhost_types.go
@@ -35,11 +35,11 @@ const (
 	BareMetalHostFinalizer string = "baremetalhost.metal3.io"
 
 	// PausedAnnotation is the annotation that pauses the reconciliation (triggers
-	// an immediate requeue).
+	// an immediate requeue)
 	PausedAnnotation = "baremetalhost.metal3.io/paused"
 
 	// DetachedAnnotation is the annotation which stops provisioner management of the host
-	// unlike in the paused case, the host status may be updated.
+	// unlike in the paused case, the host status may be updated
 	DetachedAnnotation = "baremetalhost.metal3.io/detached"
 
 	// StatusAnnotation is the annotation that keeps a copy of the Status of BMH
@@ -49,22 +49,17 @@ const (
 	StatusAnnotation = "baremetalhost.metal3.io/status"
 
 	// RebootAnnotationPrefix is the annotation which tells the host which mode to use
-	// when rebooting - hard/soft.
+	// when rebooting - hard/soft
 	RebootAnnotationPrefix = "reboot.metal3.io"
 
 	// InspectAnnotationPrefix is used to specify if automatic introspection carried out
-	// during registration of BMH is enabled or disabled.
+	// during registration of BMH is enabled or disabled
 	InspectAnnotationPrefix = "inspect.metal3.io"
 
 	// HardwareDetailsAnnotation provides the hardware details for the host
 	// in case its not already part of the host status and when introspection
-	// is disabled.
+	// is disabed
 	HardwareDetailsAnnotation = InspectAnnotationPrefix + "/hardwaredetails"
-
-	// InspectAnnotationValueDisabled is a constant string="disabled"
-	// This is particularly useful to check if inspect annotation is disabled
-	// inspect.metal3.io=disabled.
-	InspectAnnotationValueDisabled = "disabled"
 )
 
 // RootDeviceHints holds the hints for specifying the storage location
@@ -111,11 +106,11 @@ type RootDeviceHints struct {
 	Rotational *bool `json:"rotational,omitempty"`
 }
 
-// BootMode is the boot mode of the system.
+// BootMode is the boot mode of the system
 // +kubebuilder:validation:Enum=UEFI;UEFISecureBoot;legacy
 type BootMode string
 
-// Allowed boot mode from metal3.
+// Allowed boot mode from metal3
 const (
 	UEFI            BootMode = "UEFI"
 	UEFISecureBoot  BootMode = "UEFISecureBoot"
@@ -123,7 +118,7 @@ const (
 	DefaultBootMode BootMode = UEFI
 )
 
-// OperationalStatus represents the state of the host.
+// OperationalStatus represents the state of the host
 type OperationalStatus string
 
 const (
@@ -141,15 +136,15 @@ const (
 	OperationalStatusError OperationalStatus = "error"
 
 	// OperationalStatusDelayed is the status value for when the host
-	// deployment needs to be delayed to limit simultaneous hosts provisioning.
+	// deployment needs to be delayed to limit simultaneous hosts provisioning
 	OperationalStatusDelayed = "delayed"
 
 	// OperationalStatusDetached is the status value when the host is
-	// marked unmanaged via the detached annotation.
+	// marked unmanaged via the detached annotation
 	OperationalStatusDetached OperationalStatus = "detached"
 )
 
-// OperationalStatusAllowed represents the allowed values of OperationalStatus.
+// OperationalStatusAllowed represents the allowed values of OperationalStatus
 var OperationalStatusAllowed = []string{"", string(OperationalStatusOK), string(OperationalStatusDiscovered), string(OperationalStatusError), string(OperationalStatusDelayed), string(OperationalStatusDetached)}
 
 // ErrorType indicates the class of problem that has caused the Host resource
@@ -177,11 +172,11 @@ const (
 	// controller is unable to modify the power state of the Host.
 	PowerManagementError ErrorType = "power management error"
 	// DetachError is an error condition occurring when the
-	// controller is unable to detatch the host from the provisioner.
+	// controller is unable to detatch the host from the provisioner
 	DetachError ErrorType = "detach error"
 )
 
-// ErrorTypeAllowed represents the allowed values of ErrorType.
+// ErrorTypeAllowed represents the allowed values of ErrorType
 var ErrorTypeAllowed = []string{"", string(ProvisionedRegistrationError), string(RegistrationError), string(InspectionError), string(PreparationError), string(ProvisioningError), string(PowerManagementError)}
 
 // ProvisioningState defines the states the provisioner will report
@@ -189,47 +184,47 @@ var ErrorTypeAllowed = []string{"", string(ProvisionedRegistrationError), string
 type ProvisioningState string
 
 const (
-	// StateNone means the state is unknown.
+	// StateNone means the state is unknown
 	StateNone ProvisioningState = ""
 
 	// StateUnmanaged means there is insufficient information available to
-	// register the host.
+	// register the host
 	StateUnmanaged ProvisioningState = "unmanaged"
 
-	// StateRegistering means we are telling the backend about the host.
+	// StateRegistering means we are telling the backend about the host
 	StateRegistering ProvisioningState = "registering"
 
 	// StateMatchProfile used to mean we are assigning a profile.
-	// It no longer does anything, profile matching is done on registration.
+	// It no longer does anything, profile matching is done on registration
 	StateMatchProfile ProvisioningState = "match profile"
 
-	// StatePreparing means we are removing existing configuration and set new configuration to the host.
+	// StatePreparing means we are removing existing configuration and set new configuration to the host
 	StatePreparing ProvisioningState = "preparing"
 
-	// StateReady is a deprecated name for StateAvailable.
+	// StateReady is a deprecated name for StateAvailable
 	StateReady ProvisioningState = "ready"
 
-	// StateAvailable means the host can be consumed.
+	// StateAvailable means the host can be consumed
 	StateAvailable ProvisioningState = "available"
 
 	// StateProvisioning means we are writing an image to the host's
-	// disk(s).
+	// disk(s)
 	StateProvisioning ProvisioningState = "provisioning"
 
 	// StateProvisioned means we have written an image to the host's
-	// disk(s).
+	// disk(s)
 	StateProvisioned ProvisioningState = "provisioned"
 
 	// StateExternallyProvisioned means something else is managing the
-	// image on the host.
+	// image on the host
 	StateExternallyProvisioned ProvisioningState = "externally provisioned"
 
 	// StateDeprovisioning means we are removing an image from the
-	// host's disk(s).
+	// host's disk(s)
 	StateDeprovisioning ProvisioningState = "deprovisioning"
 
 	// StateInspecting means we are running the agent on the host to
-	// learn about the hardware components available there.
+	// learn about the hardware components available there
 	StateInspecting ProvisioningState = "inspecting"
 
 	// StatePoweringOffBeforeDelete means we are in the process of
@@ -237,7 +232,7 @@ const (
 	StatePoweringOffBeforeDelete ProvisioningState = "powering off before delete"
 
 	// StateDeleting means we are in the process of cleaning up the host
-	// ready for deletion.
+	// ready for deletion
 	StateDeleting ProvisioningState = "deleting"
 )
 
@@ -261,7 +256,7 @@ type BMCDetails struct {
 	DisableCertificateVerification bool `json:"disableCertificateVerification,omitempty"`
 }
 
-// HardwareRAIDVolume defines the desired configuration of volume in hardware RAID.
+// HardwareRAIDVolume defines the desired configuration of volume in hardware RAID
 type HardwareRAIDVolume struct {
 	// Size (Integer) of the logical disk to be created in GiB.
 	// If unspecified or set be 0, the maximum capacity of disk will be used for logical disk.
@@ -292,7 +287,7 @@ type HardwareRAIDVolume struct {
 	PhysicalDisks []string `json:"physicalDisks,omitempty"`
 }
 
-// SoftwareRAIDVolume defines the desired configuration of volume in software RAID.
+// SoftwareRAIDVolume defines the desired configuration of volume in software RAID
 type SoftwareRAIDVolume struct {
 	// Size (Integer) of the logical disk to be created in GiB.
 	// If unspecified or set be 0, the maximum capacity of disk will be used for logical disk.
@@ -308,7 +303,7 @@ type SoftwareRAIDVolume struct {
 	PhysicalDisks []RootDeviceHints `json:"physicalDisks,omitempty"`
 }
 
-// RAIDConfig contains the configuration that are required to config RAID in Bare Metal server.
+// RAIDConfig contains the configuration that are required to config RAID in Bare Metal server
 type RAIDConfig struct {
 	// The list of logical disks for hardware RAID, if rootDeviceHints isn't used, first volume is root volume.
 	// You can set the value of this field to `[]` to clear all the hardware RAID configurations.
@@ -330,7 +325,7 @@ type RAIDConfig struct {
 	SoftwareRAIDVolumes []SoftwareRAIDVolume `json:"softwareRAIDVolumes"`
 }
 
-// FirmwareConfig contains the configuration that you want to configure BIOS settings in Bare metal server.
+// FirmwareConfig contains the configuration that you want to configure BIOS settings in Bare metal server
 type FirmwareConfig struct {
 	// Supports the virtualization of platform hardware.
 	// This supports following options: true, false.
@@ -348,7 +343,7 @@ type FirmwareConfig struct {
 	SriovEnabled *bool `json:"sriovEnabled,omitempty"`
 }
 
-// BareMetalHostSpec defines the desired state of BareMetalHost.
+// BareMetalHostSpec defines the desired state of BareMetalHost
 type BareMetalHostSpec struct {
 	// Important: Run "make generate manifests" to regenerate code
 	// after modifying this file
@@ -448,7 +443,7 @@ type BareMetalHostSpec struct {
 // +kubebuilder:validation:Enum:=metadata;disabled
 type AutomatedCleaningMode string
 
-// Allowed automated cleaning modes.
+// Allowed automated cleaning modes
 const (
 	CleaningModeDisabled AutomatedCleaningMode = "disabled"
 	CleaningModeMetadata AutomatedCleaningMode = "metadata"
@@ -459,16 +454,16 @@ const (
 type ChecksumType string
 
 const (
-	// MD5 checksum type.
+	// MD5 checksum type
 	MD5 ChecksumType = "md5"
 
-	// SHA256 checksum type.
+	// SHA256 checksum type
 	SHA256 ChecksumType = "sha256"
 
-	// SHA512 checksum type.
+	// SHA512 checksum type
 	SHA512 ChecksumType = "sha512"
 
-	// Automatically detect.
+	// Automatically detect
 	AutoChecksum ChecksumType = "auto"
 )
 
@@ -514,16 +509,16 @@ type CustomDeploy struct {
 // +kubebuilder:validation:Format=double
 type ClockSpeed float64
 
-// ClockSpeed multipliers.
+// ClockSpeed multipliers
 const (
 	MegaHertz ClockSpeed = 1.0
 	GigaHertz            = 1000 * MegaHertz
 )
 
-// Capacity is a disk size in Bytes.
+// Capacity is a disk size in Bytes
 type Capacity int64
 
-// Capacity multipliers.
+// Capacity multipliers
 const (
 	Byte     Capacity = 1
 	KibiByte          = Byte * 1024
@@ -609,7 +604,7 @@ type Storage struct {
 // +kubebuilder:validation:Maximum=4094
 type VLANID int32
 
-// VLAN represents the name and ID of a VLAN.
+// VLAN represents the name and ID of a VLAN
 type VLAN struct {
 	ID VLANID `json:"id,omitempty"`
 
@@ -690,17 +685,17 @@ type CredentialsStatus struct {
 	Version   string                  `json:"credentialsVersion,omitempty"`
 }
 
-// RebootMode defines known variations of reboot modes.
+// RebootMode defines known variations of reboot modes
 type RebootMode string
 
 const (
-	// RebootModeHard defined for hard reset of a node.
+	// RebootModeHard defined for hard reset of a node
 	RebootModeHard RebootMode = "hard"
-	// RebootModeSoft defined for soft reset of a node.
+	// RebootModeSoft defined for soft reset of a node
 	RebootModeSoft RebootMode = "soft"
 )
 
-// RebootAnnotationArguments defines the arguments of the RebootAnnotation type.
+// RebootAnnotationArguments defines the arguments of the RebootAnnotation type
 type RebootAnnotationArguments struct {
 	Mode  RebootMode `json:"mode"`
 	Force bool       `json:"force"`
@@ -761,7 +756,7 @@ type OperationHistory struct {
 	Deprovision OperationMetric `json:"deprovision,omitempty"`
 }
 
-// BareMetalHostStatus defines the observed state of BareMetalHost.
+// BareMetalHostStatus defines the observed state of BareMetalHost
 type BareMetalHostStatus struct {
 	// Important: Run "make generate manifests" to regenerate code
 	// after modifying this file
@@ -861,8 +856,6 @@ type BareMetalHost struct {
 }
 
 // BootMode returns the boot method to use for the host.
-//
-//nolint:stylecheck
 func (host *BareMetalHost) BootMode() BootMode {
 	mode := host.Spec.BootMode
 	if mode == "" {
@@ -871,12 +864,34 @@ func (host *BareMetalHost) BootMode() BootMode {
 	return mode
 }
 
-// HasBMCDetails returns true if the BMC details are set.
+// setLabel updates the given label when necessary and returns true
+// when a change is made or false when no change is made.
+func (host *BareMetalHost) setLabel(name, value string) bool {
+	if host.Labels == nil {
+		host.Labels = make(map[string]string)
+	}
+	if host.Labels[name] != value {
+		host.Labels[name] = value
+		return true
+	}
+	return false
+}
+
+// getLabel returns the value associated with the given label. If
+// there is no value, an empty string is returned.
+func (host *BareMetalHost) getLabel(name string) string {
+	if host.Labels == nil {
+		return ""
+	}
+	return host.Labels[name]
+}
+
+// HasBMCDetails returns true if the BMC details are set
 func (host *BareMetalHost) HasBMCDetails() bool {
 	return host.Spec.BMC.Address != "" || host.Spec.BMC.CredentialsName != ""
 }
 
-// NeedsHardwareProfile returns true if the profile is not set.
+// NeedsHardwareProfile returns true if the profile is not set
 func (host *BareMetalHost) NeedsHardwareProfile() bool {
 	return host.Status.HardwareProfile == ""
 }
@@ -1063,7 +1078,7 @@ func (host *BareMetalHost) OperationMetricForState(operation ProvisioningState)
 	return
 }
 
-// GetChecksum method returns the checksum of an image.
+// GetChecksum method returns the checksum of an image
 func (image *Image) GetChecksum() (checksum, checksumType string, ok bool) {
 	if image == nil {
 		return
@@ -1098,7 +1113,7 @@ func (image *Image) GetChecksum() (checksum, checksumType string, ok bool) {
 
 // +kubebuilder:object:root=true
 
-// BareMetalHostList contains a list of BareMetalHost.
+// BareMetalHostList contains a list of BareMetalHost
 type BareMetalHostList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata,omitempty"`
diff --git a/apis/metal3.io/v1alpha1/baremetalhost_validation.go b/apis/metal3.io/v1alpha1/baremetalhost_validation.go
index ad2c85b2..e1073d85 100644
--- a/apis/metal3.io/v1alpha1/baremetalhost_validation.go
+++ b/apis/metal3.io/v1alpha1/baremetalhost_validation.go
@@ -22,7 +22,7 @@ var (
 	inspectAnnotationAllowedString = "\"disabled\" or \"\""
 )
 
-// validateHost validates BareMetalHost resource for creation.
+// validateHost validates BareMetalHost resource for creation
 func (host *BareMetalHost) validateHost() []error {
 	var errs []error
 	var bmcAccess bmc.AccessDetails
@@ -67,7 +67,7 @@ func (host *BareMetalHost) validateHost() []error {
 }
 
 // validateChanges validates BareMetalHost resource on changes
-// but also covers the validations of creation.
+// but also covers the validations of creation
 func (host *BareMetalHost) validateChanges(old *BareMetalHost) []error {
 	var errs []error
 
@@ -154,6 +154,7 @@ func validateRAID(r *RAIDConfig) []error {
 }
 
 func validateBMHName(bmhname string) error {
+
 	invalidname, _ := regexp.MatchString(`[^A-Za-z0-9\.\-\_]`, bmhname)
 	if invalidname {
 		return errors.New("BareMetalHost resource name cannot contain characters other than [A-Za-z0-9._-]")
@@ -168,6 +169,7 @@ func validateBMHName(bmhname string) error {
 }
 
 func validateDNSName(hostaddress string) error {
+
 	if hostaddress == "" {
 		return nil
 	}
@@ -181,6 +183,7 @@ func validateAnnotations(host *BareMetalHost) []error {
 	var err error
 
 	for annotation, value := range host.Annotations {
+
 		switch {
 		case annotation == StatusAnnotation:
 			err = validateStatusAnnotation(value)
@@ -204,6 +207,7 @@ func validateAnnotations(host *BareMetalHost) []error {
 
 func validateStatusAnnotation(statusAnnotation string) error {
 	if statusAnnotation != "" {
+
 		objBMHStatus := &BareMetalHostStatus{}
 
 		deco := json.NewDecoder(strings.NewReader(statusAnnotation))
@@ -221,6 +225,7 @@ func validateStatusAnnotation(statusAnnotation string) error {
 }
 
 func validateImageURL(imageURL string) error {
+
 	_, err := url.ParseRequestURI(imageURL)
 	if err != nil {
 		return fmt.Errorf("image URL %s is invalid: %w", imageURL, err)
@@ -249,8 +254,9 @@ func validateRootDeviceHints(rdh *RootDeviceHints) error {
 // When making changes to this function for operationalstatus and errortype,
 // also make the corresponding changes in the OperationalStatus and
 // ErrorType fields in the struct definition of BareMetalHostStatus in
-// the file baremetalhost_types.go.
+// the file baremetalhost_types.go
 func checkStatusAnnotation(bmhStatus *BareMetalHostStatus) error {
+
 	if !slices.Contains(OperationalStatusAllowed, string(bmhStatus.OperationalStatus)) {
 		return fmt.Errorf("invalid operationalStatus '%s' in the %s annotation", string(bmhStatus.OperationalStatus), StatusAnnotation)
 	}
diff --git a/apis/metal3.io/v1alpha1/baremetalhost_webhook.go b/apis/metal3.io/v1alpha1/baremetalhost_webhook.go
index f4138c1b..0e5f646f 100644
--- a/apis/metal3.io/v1alpha1/baremetalhost_webhook.go
+++ b/apis/metal3.io/v1alpha1/baremetalhost_webhook.go
@@ -15,7 +15,7 @@ package v1alpha1
 import (
 	"fmt"
 
-	kerrors "k8s.io/apimachinery/pkg/util/errors"
+	"k8s.io/apimachinery/pkg/util/errors"
 
 	"k8s.io/apimachinery/pkg/runtime"
 	logf "sigs.k8s.io/controller-runtime/pkg/log"
@@ -27,13 +27,13 @@ var baremetalhostlog = logf.Log.WithName("webhooks").WithName("BareMetalHost")
 
 //+kubebuilder:webhook:verbs=create;update,path=/validate-metal3-io-v1alpha1-baremetalhost,mutating=false,failurePolicy=fail,sideEffects=none,admissionReviewVersions=v1;v1beta,groups=metal3.io,resources=baremetalhosts,versions=v1alpha1,name=baremetalhost.metal3.io
 
-// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
+// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
 func (r *BareMetalHost) ValidateCreate() (admission.Warnings, error) {
 	baremetalhostlog.Info("validate create", "namespace", r.Namespace, "name", r.Name)
-	return nil, kerrors.NewAggregate(r.validateHost())
+	return nil, errors.NewAggregate(r.validateHost())
 }
 
-// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
+// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
 func (r *BareMetalHost) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
 	baremetalhostlog.Info("validate update", "namespace", r.Namespace, "name", r.Name)
 	bmh, casted := old.(*BareMetalHost)
@@ -41,10 +41,10 @@ func (r *BareMetalHost) ValidateUpdate(old runtime.Object) (admission.Warnings,
 		baremetalhostlog.Error(fmt.Errorf("old object conversion error for %s/%s", r.Namespace, r.Name), "validate update error")
 		return nil, nil
 	}
-	return nil, kerrors.NewAggregate(r.validateChanges(bmh))
+	return nil, errors.NewAggregate(r.validateChanges(bmh))
 }
 
-// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
+// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
 func (r *BareMetalHost) ValidateDelete() (admission.Warnings, error) {
 	return nil, nil
 }
diff --git a/apis/metal3.io/v1alpha1/bmceventsubscription_types.go b/apis/metal3.io/v1alpha1/bmceventsubscription_types.go
index d01c61b3..aa8b8e69 100644
--- a/apis/metal3.io/v1alpha1/bmceventsubscription_types.go
+++ b/apis/metal3.io/v1alpha1/bmceventsubscription_types.go
@@ -68,7 +68,7 @@ type BMCEventSubscription struct {
 
 // +kubebuilder:object:root=true
 
-// BMCEventSubscriptionList contains a list of BMCEventSubscriptions.
+// BMCEventSubscriptionList contains a list of BMCEventSubscriptions
 type BMCEventSubscriptionList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata,omitempty"`
diff --git a/apis/metal3.io/v1alpha1/bmceventsubscription_validation.go b/apis/metal3.io/v1alpha1/bmceventsubscription_validation.go
index 1aefae1b..96ba7544 100644
--- a/apis/metal3.io/v1alpha1/bmceventsubscription_validation.go
+++ b/apis/metal3.io/v1alpha1/bmceventsubscription_validation.go
@@ -21,7 +21,7 @@ import (
 	"net/url"
 )
 
-// validateSubscription validates BMCEventSubscription resource for creation.
+// validateSubscription validates BMCEventSubscription resource for creation
 func (s *BMCEventSubscription) validateSubscription() []error {
 	var errs []error
 
@@ -32,13 +32,16 @@ func (s *BMCEventSubscription) validateSubscription() []error {
 	if s.Spec.Destination == "" {
 		errs = append(errs, errors.New("destination cannot be empty"))
 	} else {
-		destinationURL, err := url.ParseRequestURI(s.Spec.Destination)
+		destinationUrl, err := url.ParseRequestURI(s.Spec.Destination)
 
 		if err != nil {
 			errs = append(errs, fmt.Errorf("destination is invalid: %w", err))
-		} else if destinationURL.Path == "" {
-			errs = append(errs, errors.New("hostname-only destination must have a trailing slash"))
+		} else {
+			if destinationUrl.Path == "" {
+				errs = append(errs, errors.New("hostname-only destination must have a trailing slash"))
+			}
 		}
 	}
+
 	return errs
 }
diff --git a/apis/metal3.io/v1alpha1/bmceventsubscription_webhook.go b/apis/metal3.io/v1alpha1/bmceventsubscription_webhook.go
index 3c3870bc..43a06a4c 100644
--- a/apis/metal3.io/v1alpha1/bmceventsubscription_webhook.go
+++ b/apis/metal3.io/v1alpha1/bmceventsubscription_webhook.go
@@ -15,7 +15,7 @@ package v1alpha1
 import (
 	"fmt"
 
-	kerrors "k8s.io/apimachinery/pkg/util/errors"
+	"k8s.io/apimachinery/pkg/util/errors"
 
 	"k8s.io/apimachinery/pkg/runtime"
 	logf "sigs.k8s.io/controller-runtime/pkg/log"
@@ -27,10 +27,10 @@ var bmcsubscriptionlog = logf.Log.WithName("webhooks").WithName("BMCEventSubscri
 
 //+kubebuilder:webhook:verbs=create;update,path=/validate-metal3-io-v1alpha1-bmceventsubscription,mutating=false,failurePolicy=fail,sideEffects=none,admissionReviewVersions=v1;v1beta,groups=metal3.io,resources=bmceventsubscriptions,versions=v1alpha1,name=bmceventsubscription.metal3.io
 
-// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
+// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
 func (s *BMCEventSubscription) ValidateCreate() (admission.Warnings, error) {
 	bmcsubscriptionlog.Info("validate create", "namespace", s.Namespace, "name", s.Name)
-	return nil, kerrors.NewAggregate(s.validateSubscription())
+	return nil, errors.NewAggregate(s.validateSubscription())
 }
 
 // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
@@ -52,7 +52,7 @@ func (s *BMCEventSubscription) ValidateUpdate(old runtime.Object) (admission.War
 	return nil, nil
 }
 
-// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
+// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
 func (s *BMCEventSubscription) ValidateDelete() (admission.Warnings, error) {
 	return nil, nil
 }
diff --git a/apis/metal3.io/v1alpha1/firmwareschema_types.go b/apis/metal3.io/v1alpha1/firmwareschema_types.go
index 9e9f4f5c..8c7fc852 100644
--- a/apis/metal3.io/v1alpha1/firmwareschema_types.go
+++ b/apis/metal3.io/v1alpha1/firmwareschema_types.go
@@ -25,7 +25,7 @@ import (
 	"k8s.io/apimachinery/pkg/util/intstr"
 )
 
-// Additional data describing the firmware setting.
+// Additional data describing the firmware setting
 type SettingSchema struct {
 
 	// The type of setting.
@@ -65,7 +65,8 @@ func (e SchemaSettingError) Error() string {
 }
 
 func (schema *SettingSchema) Validate(name string, value intstr.IntOrString) error {
-	if schema.ReadOnly != nil && *schema.ReadOnly {
+
+	if schema.ReadOnly != nil && *schema.ReadOnly == true {
 		return SchemaSettingError{name: name, message: "it is ReadOnly"}
 	}
 
@@ -127,7 +128,7 @@ func (schema *SettingSchema) Validate(name string, value intstr.IntOrString) err
 	}
 }
 
-// FirmwareSchemaSpec defines the desired state of FirmwareSchema.
+// FirmwareSchemaSpec defines the desired state of FirmwareSchema
 type FirmwareSchemaSpec struct {
 
 	// The hardware vendor associated with this schema
@@ -144,7 +145,7 @@ type FirmwareSchemaSpec struct {
 
 //+kubebuilder:object:root=true
 
-// FirmwareSchema is the Schema for the firmwareschemas API.
+// FirmwareSchema is the Schema for the firmwareschemas API
 type FirmwareSchema struct {
 	metav1.TypeMeta   `json:",inline"`
 	metav1.ObjectMeta `json:"metadata,omitempty"`
@@ -152,8 +153,9 @@ type FirmwareSchema struct {
 	Spec FirmwareSchemaSpec `json:"spec,omitempty"`
 }
 
-// Check whether the setting's name and value is valid using the schema.
+// Check whether the setting's name and value is valid using the schema
 func (host *FirmwareSchema) ValidateSetting(name string, value intstr.IntOrString, schemas map[string]SettingSchema) error {
+
 	schema, ok := schemas[name]
 	if !ok {
 		return SchemaSettingError{name: name, message: "it is not in the associated schema"}
@@ -164,7 +166,7 @@ func (host *FirmwareSchema) ValidateSetting(name string, value intstr.IntOrStrin
 
 //+kubebuilder:object:root=true
 
-// FirmwareSchemaList contains a list of FirmwareSchema.
+// FirmwareSchemaList contains a list of FirmwareSchema
 type FirmwareSchemaList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata,omitempty"`
diff --git a/apis/metal3.io/v1alpha1/groupversion_info.go b/apis/metal3.io/v1alpha1/groupversion_info.go
index 8b39c892..0a66d9fe 100644
--- a/apis/metal3.io/v1alpha1/groupversion_info.go
+++ b/apis/metal3.io/v1alpha1/groupversion_info.go
@@ -24,10 +24,10 @@ import (
 )
 
 var (
-	// GroupVersion is group version used to register these objects.
+	// GroupVersion is group version used to register these objects
 	GroupVersion = schema.GroupVersion{Group: "metal3.io", Version: "v1alpha1"}
 
-	// SchemeBuilder is used to add go types to the GroupVersionKind scheme.
+	// SchemeBuilder is used to add go types to the GroupVersionKind scheme
 	SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
 
 	// AddToScheme adds the types in this group-version to the given scheme.
diff --git a/apis/metal3.io/v1alpha1/hardwaredata_types.go b/apis/metal3.io/v1alpha1/hardwaredata_types.go
index a8cdb97b..82dc3ad6 100644
--- a/apis/metal3.io/v1alpha1/hardwaredata_types.go
+++ b/apis/metal3.io/v1alpha1/hardwaredata_types.go
@@ -20,7 +20,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-// HardwareDataSpec defines the desired state of HardwareData.
+// HardwareDataSpec defines the desired state of HardwareData
 type HardwareDataSpec struct {
 
 	// The hardware discovered on the host during its inspection.
@@ -31,7 +31,7 @@ type HardwareDataSpec struct {
 // +kubebuilder:resource:path=hardwaredata,scope=Namespaced,shortName=hd
 // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of HardwareData"
 
-// HardwareData is the Schema for the hardwaredata API.
+// HardwareData is the Schema for the hardwaredata API
 type HardwareData struct {
 	metav1.TypeMeta   `json:",inline"`
 	metav1.ObjectMeta `json:"metadata,omitempty"`
@@ -41,7 +41,7 @@ type HardwareData struct {
 
 //+kubebuilder:object:root=true
 
-// HardwareDataList contains a list of HardwareData.
+// HardwareDataList contains a list of HardwareData
 type HardwareDataList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata,omitempty"`
diff --git a/apis/metal3.io/v1alpha1/hostfirmwarecomponents_types.go b/apis/metal3.io/v1alpha1/hostfirmwarecomponents_types.go
index c4d3ad5f..763168f4 100644
--- a/apis/metal3.io/v1alpha1/hostfirmwarecomponents_types.go
+++ b/apis/metal3.io/v1alpha1/hostfirmwarecomponents_types.go
@@ -42,19 +42,19 @@ type FirmwareComponentStatus struct {
 type UpdatesConditionType string
 
 const (
-	// Indicates that the updates in the Spec are different than Status.
+	// Indicates that the updates in the Spec are different than Status
 	HostFirmwareComponentsChangeDetected UpdatesConditionType = "ChangeDetected"
 
-	// Indicates if the updates are valid and can be configured on the host.
+	// Indicates if the updates are valid and can be configured on the host
 	HostFirmwareComponentsValid UpdatesConditionType = "Valid"
 )
 
-// HostFirmwareComponentsSpec defines the desired state of HostFirmwareComponents.
+// HostFirmwareComponentsSpec defines the desired state of HostFirmwareComponents
 type HostFirmwareComponentsSpec struct {
 	Updates []FirmwareUpdate `json:"updates"`
 }
 
-// HostFirmwareComponentsStatus defines the observed state of HostFirmwareComponents.
+// HostFirmwareComponentsStatus defines the observed state of HostFirmwareComponents
 type HostFirmwareComponentsStatus struct {
 	// Updates is the list of all firmware components that should be updated
 	// they are specified via name and url fields.
@@ -80,7 +80,7 @@ type HostFirmwareComponentsStatus struct {
 //+kubebuilder:resource:shortName=hfc
 //+kubebuilder:subresource:status
 
-// HostFirmwareComponents is the Schema for the hostfirmwarecomponents API.
+// HostFirmwareComponents is the Schema for the hostfirmwarecomponents API
 type HostFirmwareComponents struct {
 	metav1.TypeMeta   `json:",inline"`
 	metav1.ObjectMeta `json:"metadata,omitempty"`
@@ -91,21 +91,23 @@ type HostFirmwareComponents struct {
 
 //+kubebuilder:object:root=true
 
-// HostFirmwareComponentsList contains a list of HostFirmwareComponents.
+// HostFirmwareComponentsList contains a list of HostFirmwareComponents
 type HostFirmwareComponentsList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata,omitempty"`
 	Items           []HostFirmwareComponents `json:"items"`
 }
 
-// Check whether the updates's names are valid.
+// Check whether the updates's names are valid
 func (host *HostFirmwareComponents) ValidateHostFirmwareComponents() error {
+
 	allowedNames := map[string]struct{}{"bmc": {}, "bios": {}}
 	for _, update := range host.Spec.Updates {
 		componentName := update.Component
 		if _, ok := allowedNames[componentName]; !ok {
-			return fmt.Errorf("component %s is invalid, only 'bmc' or 'bios' are allowed as update names", update.Component)
+			return fmt.Errorf("Component %s is invalid, only 'bmc' or 'bios' are allowed as update names", update.Component)
 		}
+
 	}
 
 	return nil
diff --git a/apis/metal3.io/v1alpha1/hostfirmwaresettings_types.go b/apis/metal3.io/v1alpha1/hostfirmwaresettings_types.go
index ab0b823c..c170e967 100644
--- a/apis/metal3.io/v1alpha1/hostfirmwaresettings_types.go
+++ b/apis/metal3.io/v1alpha1/hostfirmwaresettings_types.go
@@ -36,14 +36,14 @@ type SchemaReference struct {
 type SettingsConditionType string
 
 const (
-	// Indicates that the settings in the Spec are different than Status.
+	// Indicates that the settings in the Spec are different than Status
 	FirmwareSettingsChangeDetected SettingsConditionType = "ChangeDetected"
 
-	// Indicates if the settings are valid and can be configured on the host.
+	// Indicates if the settings are valid and can be configured on the host
 	FirmwareSettingsValid SettingsConditionType = "Valid"
 )
 
-// HostFirmwareSettingsSpec defines the desired state of HostFirmwareSettings.
+// HostFirmwareSettingsSpec defines the desired state of HostFirmwareSettings
 type HostFirmwareSettingsSpec struct {
 
 	// Settings are the desired firmware settings stored as name/value pairs.
@@ -51,7 +51,7 @@ type HostFirmwareSettingsSpec struct {
 	Settings DesiredSettingsMap `json:"settings" required:"true"`
 }
 
-// HostFirmwareSettingsStatus defines the observed state of HostFirmwareSettings.
+// HostFirmwareSettingsStatus defines the observed state of HostFirmwareSettings
 type HostFirmwareSettingsStatus struct {
 	// FirmwareSchema is a reference to the Schema used to describe each
 	// FirmwareSetting. By default, this will be a Schema in the same
@@ -78,7 +78,7 @@ type HostFirmwareSettingsStatus struct {
 //+kubebuilder:resource:shortName=hfs
 //+kubebuilder:subresource:status
 
-// HostFirmwareSettings is the Schema for the hostfirmwaresettings API.
+// HostFirmwareSettings is the Schema for the hostfirmwaresettings API
 type HostFirmwareSettings struct {
 	metav1.TypeMeta   `json:",inline"`
 	metav1.ObjectMeta `json:"metadata,omitempty"`
@@ -89,7 +89,7 @@ type HostFirmwareSettings struct {
 
 //+kubebuilder:object:root=true
 
-// HostFirmwareSettingsList contains a list of HostFirmwareSettings.
+// HostFirmwareSettingsList contains a list of HostFirmwareSettings
 type HostFirmwareSettingsList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata,omitempty"`
diff --git a/apis/metal3.io/v1alpha1/preprovisioningimage_types.go b/apis/metal3.io/v1alpha1/preprovisioningimage_types.go
index fd655538..7345d77b 100644
--- a/apis/metal3.io/v1alpha1/preprovisioningimage_types.go
+++ b/apis/metal3.io/v1alpha1/preprovisioningimage_types.go
@@ -29,7 +29,7 @@ const (
 	ImageFormatInitRD ImageFormat = "initrd"
 )
 
-// PreprovisioningImageSpec defines the desired state of PreprovisioningImage.
+// PreprovisioningImageSpec defines the desired state of PreprovisioningImage
 type PreprovisioningImageSpec struct {
 	// networkDataName is the name of a Secret in the local namespace that
 	// contains network data to build in to the image.
@@ -60,15 +60,15 @@ const (
 	ConditionImageError ImageStatusConditionType = "Error"
 )
 
-// PreprovisioningImageStatus defines the observed state of PreprovisioningImage.
+// PreprovisioningImageStatus defines the observed state of PreprovisioningImage
 type PreprovisioningImageStatus struct {
 	// imageUrl is the URL from which the built image can be downloaded.
-	ImageUrl string `json:"imageUrl,omitempty"` //nolint:revive,stylecheck
+	ImageUrl string `json:"imageUrl,omitempty"`
 
 	// kernelUrl is the URL from which the kernel of the image can be downloaded.
 	// Only makes sense for initrd images.
 	// +optional
-	KernelUrl string `json:"kernelUrl,omitempty"` //nolint:revive,stylecheck
+	KernelUrl string `json:"kernelUrl,omitempty"`
 
 	// extraKernelParams is a string with extra parameters to pass to the
 	// kernel when booting the image over network. Only makes sense for initrd images.
@@ -103,7 +103,7 @@ type PreprovisioningImageStatus struct {
 // +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].reason",description="The reason for the image readiness status"
 // +kubebuilder:subresource:status
 
-// PreprovisioningImage is the Schema for the preprovisioningimages API.
+// PreprovisioningImage is the Schema for the preprovisioningimages API
 type PreprovisioningImage struct {
 	metav1.TypeMeta   `json:",inline"`
 	metav1.ObjectMeta `json:"metadata,omitempty"`
@@ -114,7 +114,7 @@ type PreprovisioningImage struct {
 
 // +kubebuilder:object:root=true
 
-// PreprovisioningImageList contains a list of PreprovisioningImage.
+// PreprovisioningImageList contains a list of PreprovisioningImage
 type PreprovisioningImageList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata,omitempty"`
diff --git a/apis/metal3.io/v1alpha1/profile/profile.go b/apis/metal3.io/v1alpha1/profile/profile.go
index 03ee2a87..e0029c76 100644
--- a/apis/metal3.io/v1alpha1/profile/profile.go
+++ b/apis/metal3.io/v1alpha1/profile/profile.go
@@ -3,7 +3,7 @@ package profile
 import (
 	"fmt"
 
-	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
+	metal3v1alpha1 "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
 )
 
 const (
@@ -22,7 +22,7 @@ type Profile struct {
 
 	// RootDeviceHints holds the suggestions for placing the storage
 	// for the root filesystem.
-	RootDeviceHints metal3api.RootDeviceHints
+	RootDeviceHints metal3v1alpha1.RootDeviceHints
 }
 
 var profiles = make(map[string]Profile)
@@ -30,35 +30,35 @@ var profiles = make(map[string]Profile)
 func init() {
 	profiles[DefaultProfileName] = Profile{
 		Name: DefaultProfileName,
-		RootDeviceHints: metal3api.RootDeviceHints{
+		RootDeviceHints: metal3v1alpha1.RootDeviceHints{
 			DeviceName: "/dev/sda",
 		},
 	}
 
 	profiles["libvirt"] = Profile{
 		Name: "libvirt",
-		RootDeviceHints: metal3api.RootDeviceHints{
+		RootDeviceHints: metal3v1alpha1.RootDeviceHints{
 			DeviceName: "/dev/vda",
 		},
 	}
 
 	profiles["dell"] = Profile{
 		Name: "dell",
-		RootDeviceHints: metal3api.RootDeviceHints{
+		RootDeviceHints: metal3v1alpha1.RootDeviceHints{
 			HCTL: "0:0:0:0",
 		},
 	}
 
 	profiles["dell-raid"] = Profile{
 		Name: "dell-raid",
-		RootDeviceHints: metal3api.RootDeviceHints{
+		RootDeviceHints: metal3v1alpha1.RootDeviceHints{
 			HCTL: "0:2:0:0",
 		},
 	}
 
 	profiles["openstack"] = Profile{
 		Name: "openstack",
-		RootDeviceHints: metal3api.RootDeviceHints{
+		RootDeviceHints: metal3v1alpha1.RootDeviceHints{
 			DeviceName: "/dev/vdb",
 		},
 	}
@@ -68,11 +68,11 @@ func init() {
 	}
 }
 
-// GetProfile returns the named profile.
+// GetProfile returns the named profile
 func GetProfile(name string) (Profile, error) {
 	profile, ok := profiles[name]
 	if !ok {
-		return Profile{}, fmt.Errorf("no hardware profile named %q", name)
+		return Profile{}, fmt.Errorf("No hardware profile named %q", name)
 	}
 	return profile, nil
 }
diff --git a/cmd/make-virt-host/main.go b/cmd/make-virt-host/main.go
index 9b94c726..b5130665 100644
--- a/cmd/make-virt-host/main.go
+++ b/cmd/make-virt-host/main.go
@@ -156,7 +156,7 @@ func main() {
 	}
 
 	domainResult := Domain{}
-	xml.Unmarshal(virshOut, &domainResult)
+	xml.Unmarshal([]byte(virshOut), &domainResult)
 	if *verbose {
 		fmt.Printf("%v\n", domainResult)
 	}
@@ -192,7 +192,7 @@ func main() {
 	}
 
 	var vbmcResult []VBMC
-	json.Unmarshal(vbmcOut, &vbmcResult)
+	json.Unmarshal([]byte(vbmcOut), &vbmcResult)
 	nameToPort := make(map[string]int)
 	for _, vbmc := range vbmcResult {
 		if *verbose {
diff --git a/config/base/crds/bases/metal3.io_baremetalhosts.yaml b/config/base/crds/bases/metal3.io_baremetalhosts.yaml
index 007f1e7a..d2aa2121 100644
--- a/config/base/crds/bases/metal3.io_baremetalhosts.yaml
+++ b/config/base/crds/bases/metal3.io_baremetalhosts.yaml
@@ -71,7 +71,7 @@ spec:
           metadata:
             type: object
           spec:
-            description: BareMetalHostSpec defines the desired state of BareMetalHost.
+            description: BareMetalHostSpec defines the desired state of BareMetalHost
             properties:
               architecture:
                 description: CPU architecture of the host, e.g. "x86_64" or "aarch64".
@@ -298,7 +298,7 @@ spec:
                       of this field to `[]` to clear all the hardware RAID configurations.
                     items:
                       description: HardwareRAIDVolume defines the desired configuration
-                        of volume in hardware RAID.
+                        of volume in hardware RAID
                       properties:
                         controller:
                           description: The name of the RAID controller to use
@@ -363,7 +363,7 @@ spec:
                       will always be deleted.
                     items:
                       description: SoftwareRAIDVolume defines the desired configuration
-                        of volume in software RAID.
+                        of volume in software RAID
                       properties:
                         level:
                           description: 'RAID level for the logical disk. The following
@@ -533,7 +533,7 @@ spec:
             - online
             type: object
           status:
-            description: BareMetalHostStatus defines the observed state of BareMetalHost.
+            description: BareMetalHostStatus defines the observed state of BareMetalHost
             properties:
               errorCount:
                 default: 0
@@ -650,7 +650,7 @@ spec:
                         vlans:
                           description: The VLANs available
                           items:
-                            description: VLAN represents the name and ID of a VLAN.
+                            description: VLAN represents the name and ID of a VLAN
                             properties:
                               id:
                                 description: VLANID is a 12-bit 802.1Q VLAN identifier
@@ -913,7 +913,7 @@ spec:
                           the hardware RAID configurations.
                         items:
                           description: HardwareRAIDVolume defines the desired configuration
-                            of volume in hardware RAID.
+                            of volume in hardware RAID
                           properties:
                             controller:
                               description: The name of the RAID controller to use
@@ -979,7 +979,7 @@ spec:
                           RAID will always be deleted.
                         items:
                           description: SoftwareRAIDVolume defines the desired configuration
-                            of volume in software RAID.
+                            of volume in software RAID
                           properties:
                             level:
                               description: 'RAID level for the logical disk. The following
diff --git a/config/base/crds/bases/metal3.io_firmwareschemas.yaml b/config/base/crds/bases/metal3.io_firmwareschemas.yaml
index b95f5d3c..4f25a90d 100644
--- a/config/base/crds/bases/metal3.io_firmwareschemas.yaml
+++ b/config/base/crds/bases/metal3.io_firmwareschemas.yaml
@@ -17,7 +17,7 @@ spec:
   - name: v1alpha1
     schema:
       openAPIV3Schema:
-        description: FirmwareSchema is the Schema for the firmwareschemas API.
+        description: FirmwareSchema is the Schema for the firmwareschemas API
         properties:
           apiVersion:
             description: 'APIVersion defines the versioned schema of this representation
@@ -32,7 +32,7 @@ spec:
           metadata:
             type: object
           spec:
-            description: FirmwareSchemaSpec defines the desired state of FirmwareSchema.
+            description: FirmwareSchemaSpec defines the desired state of FirmwareSchema
             properties:
               hardwareModel:
                 description: The hardware model associated with this schema
@@ -42,7 +42,7 @@ spec:
                 type: string
               schema:
                 additionalProperties:
-                  description: Additional data describing the firmware setting.
+                  description: Additional data describing the firmware setting
                   properties:
                     allowable_values:
                       description: The allowable value for an Enumeration type setting.
diff --git a/config/base/crds/bases/metal3.io_hardwaredata.yaml b/config/base/crds/bases/metal3.io_hardwaredata.yaml
index 890ba639..0f78fcc8 100644
--- a/config/base/crds/bases/metal3.io_hardwaredata.yaml
+++ b/config/base/crds/bases/metal3.io_hardwaredata.yaml
@@ -24,7 +24,7 @@ spec:
     name: v1alpha1
     schema:
       openAPIV3Schema:
-        description: HardwareData is the Schema for the hardwaredata API.
+        description: HardwareData is the Schema for the hardwaredata API
         properties:
           apiVersion:
             description: 'APIVersion defines the versioned schema of this representation
@@ -39,7 +39,7 @@ spec:
           metadata:
             type: object
           spec:
-            description: HardwareDataSpec defines the desired state of HardwareData.
+            description: HardwareDataSpec defines the desired state of HardwareData
             properties:
               hardware:
                 description: The hardware discovered on the host during its inspection.
@@ -117,7 +117,7 @@ spec:
                         vlans:
                           description: The VLANs available
                           items:
-                            description: VLAN represents the name and ID of a VLAN.
+                            description: VLAN represents the name and ID of a VLAN
                             properties:
                               id:
                                 description: VLANID is a 12-bit 802.1Q VLAN identifier
diff --git a/config/base/crds/bases/metal3.io_hostfirmwarecomponents.yaml b/config/base/crds/bases/metal3.io_hostfirmwarecomponents.yaml
index 292348e5..f9bb7008 100644
--- a/config/base/crds/bases/metal3.io_hostfirmwarecomponents.yaml
+++ b/config/base/crds/bases/metal3.io_hostfirmwarecomponents.yaml
@@ -20,7 +20,7 @@ spec:
     schema:
       openAPIV3Schema:
         description: HostFirmwareComponents is the Schema for the hostfirmwarecomponents
-          API.
+          API
         properties:
           apiVersion:
             description: 'APIVersion defines the versioned schema of this representation
@@ -35,7 +35,7 @@ spec:
           metadata:
             type: object
           spec:
-            description: HostFirmwareComponentsSpec defines the desired state of HostFirmwareComponents.
+            description: HostFirmwareComponentsSpec defines the desired state of HostFirmwareComponents
             properties:
               updates:
                 items:
@@ -55,7 +55,7 @@ spec:
             type: object
           status:
             description: HostFirmwareComponentsStatus defines the observed state of
-              HostFirmwareComponents.
+              HostFirmwareComponents
             properties:
               components:
                 description: Components is the list of all available firmware components
diff --git a/config/base/crds/bases/metal3.io_hostfirmwaresettings.yaml b/config/base/crds/bases/metal3.io_hostfirmwaresettings.yaml
index b079db04..f6f799e7 100644
--- a/config/base/crds/bases/metal3.io_hostfirmwaresettings.yaml
+++ b/config/base/crds/bases/metal3.io_hostfirmwaresettings.yaml
@@ -20,7 +20,7 @@ spec:
     schema:
       openAPIV3Schema:
         description: HostFirmwareSettings is the Schema for the hostfirmwaresettings
-          API.
+          API
         properties:
           apiVersion:
             description: 'APIVersion defines the versioned schema of this representation
@@ -35,7 +35,7 @@ spec:
           metadata:
             type: object
           spec:
-            description: HostFirmwareSettingsSpec defines the desired state of HostFirmwareSettings.
+            description: HostFirmwareSettingsSpec defines the desired state of HostFirmwareSettings
             properties:
               settings:
                 additionalProperties:
@@ -51,7 +51,7 @@ spec:
             type: object
           status:
             description: HostFirmwareSettingsStatus defines the observed state of
-              HostFirmwareSettings.
+              HostFirmwareSettings
             properties:
               conditions:
                 description: Track whether settings stored in the spec are valid based
diff --git a/config/base/crds/bases/metal3.io_preprovisioningimages.yaml b/config/base/crds/bases/metal3.io_preprovisioningimages.yaml
index 127d97fc..dac8d3b6 100644
--- a/config/base/crds/bases/metal3.io_preprovisioningimages.yaml
+++ b/config/base/crds/bases/metal3.io_preprovisioningimages.yaml
@@ -29,7 +29,7 @@ spec:
     schema:
       openAPIV3Schema:
         description: PreprovisioningImage is the Schema for the preprovisioningimages
-          API.
+          API
         properties:
           apiVersion:
             description: 'APIVersion defines the versioned schema of this representation
@@ -44,7 +44,7 @@ spec:
           metadata:
             type: object
           spec:
-            description: PreprovisioningImageSpec defines the desired state of PreprovisioningImage.
+            description: PreprovisioningImageSpec defines the desired state of PreprovisioningImage
             properties:
               acceptFormats:
                 description: acceptFormats is a list of acceptable image formats.
@@ -66,7 +66,7 @@ spec:
             type: object
           status:
             description: PreprovisioningImageStatus defines the observed state of
-              PreprovisioningImage.
+              PreprovisioningImage
             properties:
               architecture:
                 description: architecture is the processor architecture for which
diff --git a/config/overlays/fixture-release-0.3/kustomization.yaml b/config/overlays/fixture-release-0.3/kustomization.yaml
deleted file mode 100644
index 9cf655b3..00000000
--- a/config/overlays/fixture-release-0.3/kustomization.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-resources:
-- https://github.com/metal3-io/baremetal-operator/config/namespace?ref=release-0.3
-- https://github.com/metal3-io/baremetal-operator/config/default?ref=release-0.3
-patches:
-- patch: |
-    # Enable test mode (fixture provider instead of ironic)
-    - op: add
-      path: /spec/template/spec/containers/0/args/-
-      value: --test-mode
-    # Don't try to pull again the pre-loaded image
-    - op: replace
-      path: /spec/template/spec/containers/0/imagePullPolicy
-      value: IfNotPresent
-  target:
-    kind: Deployment
-    name: controller-manager
-images:
-- name: quay.io/metal3-io/baremetal-operator
-  newTag: release-0.3
diff --git a/config/overlays/fixture-release-0.4/kustomization.yaml b/config/overlays/fixture-release-0.4/kustomization.yaml
index 5c6f1efa..559c0097 100644
--- a/config/overlays/fixture-release-0.4/kustomization.yaml
+++ b/config/overlays/fixture-release-0.4/kustomization.yaml
@@ -1,8 +1,10 @@
 apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
+
 resources:
 - https://github.com/metal3-io/baremetal-operator/config/namespace?ref=release-0.4
 - https://github.com/metal3-io/baremetal-operator/config/default?ref=release-0.4
+
 patches:
 - patch: |
     # Enable test mode (fixture provider instead of ironic)
@@ -16,6 +18,7 @@ patches:
   target:
     kind: Deployment
     name: controller-manager
+
 images:
 - name: quay.io/metal3-io/baremetal-operator
   newTag: release-0.4
diff --git a/config/overlays/fixture-release-0.5/kustomization.yaml b/config/overlays/fixture-release-0.5/kustomization.yaml
deleted file mode 100644
index 4600b60d..00000000
--- a/config/overlays/fixture-release-0.5/kustomization.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-resources:
-- https://github.com/metal3-io/baremetal-operator/config/namespace?ref=release-0.5
-- https://github.com/metal3-io/baremetal-operator/config/default?ref=release-0.5
-patches:
-- patch: |
-    # Enable test mode (fixture provider instead of ironic)
-    - op: add
-      path: /spec/template/spec/containers/0/args/-
-      value: --test-mode
-    # Don't try to pull again the pre-loaded image
-    - op: replace
-      path: /spec/template/spec/containers/0/imagePullPolicy
-      value: IfNotPresent
-  target:
-    kind: Deployment
-    name: controller-manager
-images:
-- name: quay.io/metal3-io/baremetal-operator
-  newTag: release-0.5
diff --git a/config/render/capm3.yaml b/config/render/capm3.yaml
index d7e11406..f013ce50 100644
--- a/config/render/capm3.yaml
+++ b/config/render/capm3.yaml
@@ -71,7 +71,7 @@ spec:
           metadata:
             type: object
           spec:
-            description: BareMetalHostSpec defines the desired state of BareMetalHost.
+            description: BareMetalHostSpec defines the desired state of BareMetalHost
             properties:
               architecture:
                 description: CPU architecture of the host, e.g. "x86_64" or "aarch64".
@@ -298,7 +298,7 @@ spec:
                       of this field to `[]` to clear all the hardware RAID configurations.
                     items:
                       description: HardwareRAIDVolume defines the desired configuration
-                        of volume in hardware RAID.
+                        of volume in hardware RAID
                       properties:
                         controller:
                           description: The name of the RAID controller to use
@@ -363,7 +363,7 @@ spec:
                       will always be deleted.
                     items:
                       description: SoftwareRAIDVolume defines the desired configuration
-                        of volume in software RAID.
+                        of volume in software RAID
                       properties:
                         level:
                           description: 'RAID level for the logical disk. The following
@@ -533,7 +533,7 @@ spec:
             - online
             type: object
           status:
-            description: BareMetalHostStatus defines the observed state of BareMetalHost.
+            description: BareMetalHostStatus defines the observed state of BareMetalHost
             properties:
               errorCount:
                 default: 0
@@ -650,7 +650,7 @@ spec:
                         vlans:
                           description: The VLANs available
                           items:
-                            description: VLAN represents the name and ID of a VLAN.
+                            description: VLAN represents the name and ID of a VLAN
                             properties:
                               id:
                                 description: VLANID is a 12-bit 802.1Q VLAN identifier
@@ -913,7 +913,7 @@ spec:
                           the hardware RAID configurations.
                         items:
                           description: HardwareRAIDVolume defines the desired configuration
-                            of volume in hardware RAID.
+                            of volume in hardware RAID
                           properties:
                             controller:
                               description: The name of the RAID controller to use
@@ -979,7 +979,7 @@ spec:
                           RAID will always be deleted.
                         items:
                           description: SoftwareRAIDVolume defines the desired configuration
-                            of volume in software RAID.
+                            of volume in software RAID
                           properties:
                             level:
                               description: 'RAID level for the logical disk. The following
@@ -1245,7 +1245,7 @@ spec:
   - name: v1alpha1
     schema:
       openAPIV3Schema:
-        description: FirmwareSchema is the Schema for the firmwareschemas API.
+        description: FirmwareSchema is the Schema for the firmwareschemas API
         properties:
           apiVersion:
             description: 'APIVersion defines the versioned schema of this representation
@@ -1260,7 +1260,7 @@ spec:
           metadata:
             type: object
           spec:
-            description: FirmwareSchemaSpec defines the desired state of FirmwareSchema.
+            description: FirmwareSchemaSpec defines the desired state of FirmwareSchema
             properties:
               hardwareModel:
                 description: The hardware model associated with this schema
@@ -1270,7 +1270,7 @@ spec:
                 type: string
               schema:
                 additionalProperties:
-                  description: Additional data describing the firmware setting.
+                  description: Additional data describing the firmware setting
                   properties:
                     allowable_values:
                       description: The allowable value for an Enumeration type setting.
@@ -1340,7 +1340,7 @@ spec:
     name: v1alpha1
     schema:
       openAPIV3Schema:
-        description: HardwareData is the Schema for the hardwaredata API.
+        description: HardwareData is the Schema for the hardwaredata API
         properties:
           apiVersion:
             description: 'APIVersion defines the versioned schema of this representation
@@ -1355,7 +1355,7 @@ spec:
           metadata:
             type: object
           spec:
-            description: HardwareDataSpec defines the desired state of HardwareData.
+            description: HardwareDataSpec defines the desired state of HardwareData
             properties:
               hardware:
                 description: The hardware discovered on the host during its inspection.
@@ -1433,7 +1433,7 @@ spec:
                         vlans:
                           description: The VLANs available
                           items:
-                            description: VLAN represents the name and ID of a VLAN.
+                            description: VLAN represents the name and ID of a VLAN
                             properties:
                               id:
                                 description: VLANID is a 12-bit 802.1Q VLAN identifier
@@ -1545,7 +1545,7 @@ spec:
     schema:
       openAPIV3Schema:
         description: HostFirmwareSettings is the Schema for the hostfirmwaresettings
-          API.
+          API
         properties:
           apiVersion:
             description: 'APIVersion defines the versioned schema of this representation
@@ -1560,7 +1560,7 @@ spec:
           metadata:
             type: object
           spec:
-            description: HostFirmwareSettingsSpec defines the desired state of HostFirmwareSettings.
+            description: HostFirmwareSettingsSpec defines the desired state of HostFirmwareSettings
             properties:
               settings:
                 additionalProperties:
@@ -1576,7 +1576,7 @@ spec:
             type: object
           status:
             description: HostFirmwareSettingsStatus defines the observed state of
-              HostFirmwareSettings.
+              HostFirmwareSettings
             properties:
               conditions:
                 description: Track whether settings stored in the spec are valid based
@@ -1716,7 +1716,7 @@ spec:
     schema:
       openAPIV3Schema:
         description: PreprovisioningImage is the Schema for the preprovisioningimages
-          API.
+          API
         properties:
           apiVersion:
             description: 'APIVersion defines the versioned schema of this representation
@@ -1731,7 +1731,7 @@ spec:
           metadata:
             type: object
           spec:
-            description: PreprovisioningImageSpec defines the desired state of PreprovisioningImage.
+            description: PreprovisioningImageSpec defines the desired state of PreprovisioningImage
             properties:
               acceptFormats:
                 description: acceptFormats is a list of acceptable image formats.
@@ -1753,7 +1753,7 @@ spec:
             type: object
           status:
             description: PreprovisioningImageStatus defines the observed state of
-              PreprovisioningImage.
+              PreprovisioningImage
             properties:
               architecture:
                 description: architecture is the processor architecture for which
diff --git a/controllers/metal3.io/action_result.go b/controllers/metal3.io/action_result.go
index 903a7f12..eb1d7fed 100644
--- a/controllers/metal3.io/action_result.go
+++ b/controllers/metal3.io/action_result.go
@@ -85,7 +85,7 @@ func (r actionComplete) Dirty() bool {
 // deleteComplete is a result indicating that the deletion action has
 // completed, and that the resource has now been deleted.
 type deleteComplete struct {
-	actionComplete //nolint:unused
+	actionComplete
 }
 
 func (r deleteComplete) Result() (result reconcile.Result, err error) {
diff --git a/controllers/metal3.io/baremetalhost_controller.go b/controllers/metal3.io/baremetalhost_controller.go
index e22726a2..6b68f7f4 100644
--- a/controllers/metal3.io/baremetalhost_controller.go
+++ b/controllers/metal3.io/baremetalhost_controller.go
@@ -75,6 +75,7 @@ type reconcileInfo struct {
 	request           ctrl.Request
 	bmcCredsSecret    *corev1.Secret
 	events            []corev1.Event
+	errorMessage      string
 	postSaveCallbacks []func()
 }
 
@@ -437,7 +438,7 @@ func clearRebootAnnotations(host *metal3api.BareMetalHost) (dirty bool) {
 // which means we don't inspect even in Inspecting state.
 func inspectionDisabled(host *metal3api.BareMetalHost) bool {
 	annotations := host.GetAnnotations()
-	return annotations[metal3api.InspectAnnotationPrefix] == metal3api.InspectAnnotationValueDisabled
+	return annotations[metal3api.InspectAnnotationPrefix] == "disabled"
 }
 
 // hasInspectAnnotation checks for existence of inspect.metal3.io annotation
@@ -445,7 +446,7 @@ func inspectionDisabled(host *metal3api.BareMetalHost) bool {
 func hasInspectAnnotation(host *metal3api.BareMetalHost) bool {
 	annotations := host.GetAnnotations()
 	if annotations != nil {
-		if expect, ok := annotations[metal3api.InspectAnnotationPrefix]; ok && expect != metal3api.InspectAnnotationValueDisabled {
+		if expect, ok := annotations[metal3api.InspectAnnotationPrefix]; ok && expect != "disabled" {
 			return true
 		}
 	}
diff --git a/controllers/metal3.io/bmceventsubscription_controller.go b/controllers/metal3.io/bmceventsubscription_controller.go
index 89311557..1fe3c273 100644
--- a/controllers/metal3.io/bmceventsubscription_controller.go
+++ b/controllers/metal3.io/bmceventsubscription_controller.go
@@ -37,6 +37,7 @@ 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/secretutils"
 	"github.com/metal3-io/baremetal-operator/pkg/utils"
 )
 
@@ -87,7 +88,7 @@ func (r *BMCEventSubscriptionReconciler) Reconcile(ctx context.Context, request
 		if k8serrors.IsNotFound(err) {
 			reqLogger.Error(err, "baremetalhost not found", "host", subscription.Spec.HostName)
 
-			message := fmt.Sprintf("baremetal host %q", subscription.Status.Error)
+			message := fmt.Sprintf("baremetal host \"%s\"", subscription.Status.Error)
 			return r.handleError(ctx, subscription, err, message, true)
 		}
 		// Error reading the object - requeue the request.
@@ -234,6 +235,10 @@ func (r *BMCEventSubscriptionReconciler) getProvisioner(request ctrl.Request, ho
 	return prov, ready, nil
 }
 
+func (r *BMCEventSubscriptionReconciler) secretManager(log logr.Logger) secretutils.SecretManager {
+	return secretutils.NewSecretManager(log, r.Client, r.APIReader)
+}
+
 func (r *BMCEventSubscriptionReconciler) getHTTPHeaders(subscription metal3api.BMCEventSubscription) ([]map[string]string, error) {
 	headers := []map[string]string{}
 
diff --git a/controllers/metal3.io/host_config_data.go b/controllers/metal3.io/host_config_data.go
index 0a298e24..8b668565 100644
--- a/controllers/metal3.io/host_config_data.go
+++ b/controllers/metal3.io/host_config_data.go
@@ -93,7 +93,7 @@ func (hcd *hostConfigData) NetworkData() (string, error) {
 	return networkDataRaw, err
 }
 
-// PreprovisioningNetworkData get preprovisioning network configuration.
+// PreprovisioningNetworkData get preprovisioning network configuration
 func (hcd *hostConfigData) PreprovisioningNetworkData() (string, error) {
 	if hcd.host.Spec.PreprovisioningNetworkDataName == "" {
 		return "", nil
@@ -113,7 +113,7 @@ func (hcd *hostConfigData) PreprovisioningNetworkData() (string, error) {
 	return networkDataRaw, err
 }
 
-// MetaData get host metatdata.
+// MetaData get host metatdata
 func (hcd *hostConfigData) MetaData() (string, error) {
 	if hcd.host.Spec.MetaData == nil {
 		hcd.log.Info("MetaData is not set returning empty(nil) data")
diff --git a/go.mod b/go.mod
index aefd9a9f..6c78143e 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/metal3-io/baremetal-operator
 
-go 1.21
+go 1.20
 
 require (
 	github.com/go-logr/logr v1.4.1
@@ -12,7 +12,7 @@ require (
 	github.com/pkg/errors v0.9.1
 	github.com/prometheus/client_golang v1.18.0
 	github.com/stretchr/testify v1.8.4
-	go.etcd.io/etcd/client/pkg/v3 v3.5.12
+	go.etcd.io/etcd/client/pkg/v3 v3.5.11
 	go.uber.org/zap v1.26.0
 	golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
 	k8s.io/api v0.28.5
diff --git a/go.sum b/go.sum
index d7094d58..23630364 100644
--- a/go.sum
+++ b/go.sum
@@ -29,7 +29,6 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En
 github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
 github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
 github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
-github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
@@ -48,7 +47,6 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
 github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
 github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
-github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/safetext v0.0.0-20230106111101-7156a760e523 h1:i4NsbmB9pD5+Ggp5GZKyvYY6MkjvPE8CIMlkvXFF8gA=
 github.com/google/safetext v0.0.0-20230106111101-7156a760e523/go.mod h1:mJNEy0r5YPHC7ChQffpOszlGB4L1iqjXWpIEKcFpr9s=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -69,7 +67,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
-github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -86,7 +83,6 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
-github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
 github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
 github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -103,7 +99,6 @@ github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGy
 github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
 github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
 github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
-github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
 github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
@@ -122,12 +117,11 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-go.etcd.io/etcd/client/pkg/v3 v3.5.12 h1:EYDL6pWwyOsylrQyLp2w+HkQ46ATiOvoEdMarindU2A=
-go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4=
+go.etcd.io/etcd/client/pkg/v3 v3.5.11 h1:bT2xVspdiCj2910T0V+/KHcVKjkUrCZVtk8J2JF2z1A=
+go.etcd.io/etcd/client/pkg/v3 v3.5.11/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
 go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
-go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
 go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
@@ -184,7 +178,6 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
-golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/hack/generate.sh b/hack/generate.sh
index fec759d1..ef4b67d6 100755
--- a/hack/generate.sh
+++ b/hack/generate.sh
@@ -31,6 +31,6 @@ else
     --volume "${PWD}:/go/src/github.com/metal3-io/baremetal-operator:rw,z" \
     --entrypoint sh \
     --workdir /go/src/github.com/metal3-io/baremetal-operator \
-    docker.io/golang:1.21 \
+    docker.io/golang:1.20 \
     /go/src/github.com/metal3-io/baremetal-operator/hack/generate.sh "${@}"
 fi;
diff --git a/hack/gofmt.sh b/hack/gofmt.sh
index 81084cba..8048ee36 100755
--- a/hack/gofmt.sh
+++ b/hack/gofmt.sh
@@ -22,6 +22,6 @@ else
     --volume "${PWD}:/workdir:rw,z" \
     --entrypoint sh \
     --workdir /workdir \
-    docker.io/golang:1.21 \
+    docker.io/golang:1.20 \
     /workdir/hack/gofmt.sh "${@}"
 fi;
diff --git a/hack/golint.sh b/hack/golint.sh
index 15e7f75a..80c8c17b 100755
--- a/hack/golint.sh
+++ b/hack/golint.sh
@@ -15,6 +15,6 @@ else
     --volume "${PWD}:/go/src/github.com/metal3-io/baremetal-operator:rw,z" \
     --entrypoint sh \
     --workdir /go/src/github.com/metal3-io/baremetal-operator \
-    docker.io/golang:1.21 \
+    docker.io/golang:1.20 \
     /go/src/github.com/metal3-io/baremetal-operator/hack/golint.sh "${@}"
 fi;
diff --git a/hack/gomod.sh b/hack/gomod.sh
index f088bc7b..9195fd4c 100755
--- a/hack/gomod.sh
+++ b/hack/gomod.sh
@@ -39,6 +39,6 @@ else
         --volume "${PWD}:/workdir:ro,z" \
         --entrypoint sh \
         --workdir /workdir \
-        docker.io/golang:1.21 \
+        docker.io/golang:1.20 \
         /workdir/hack/gomod.sh "$@"
 fi
diff --git a/hack/tools/go.mod b/hack/tools/go.mod
index 58c4391a..e9b04ca6 100644
--- a/hack/tools/go.mod
+++ b/hack/tools/go.mod
@@ -1,6 +1,6 @@
 module github.com/metal3-io/baremetal-operator/tooling
 
-go 1.21
+go 1.20
 
 require (
 	sigs.k8s.io/controller-tools v0.12.1
diff --git a/hack/tools/go.sum b/hack/tools/go.sum
index 99351b15..87f166a4 100644
--- a/hack/tools/go.sum
+++ b/hack/tools/go.sum
@@ -20,7 +20,6 @@ github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQL
 github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
 github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
 github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
-github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
 github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
 github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
 github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -103,11 +102,9 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
 github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
 github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
 github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
-github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
 github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
 github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
-github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
 github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA=
 github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
@@ -118,10 +115,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
-github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
-github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
 github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -173,7 +168,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
 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=
 golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
-golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -228,7 +222,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
-gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
diff --git a/hack/unit.sh b/hack/unit.sh
index 04b6a6e1..e759f3f9 100755
--- a/hack/unit.sh
+++ b/hack/unit.sh
@@ -24,6 +24,6 @@ else
     --volume "${PWD}:/go/src/github.com/metal3-io/baremetal-operator:rw,z" \
     --entrypoint sh \
     --workdir /go/src/github.com/metal3-io/baremetal-operator \
-    docker.io/golang:1.21 \
+    docker.io/golang:1.20 \
     /go/src/github.com/metal3-io/baremetal-operator/hack/unit.sh "${@}"
 fi;
diff --git a/pkg/hardwareutils/bmc/access.go b/pkg/hardwareutils/bmc/access.go
index 73eaa7c7..f00770f6 100644
--- a/pkg/hardwareutils/bmc/access.go
+++ b/pkg/hardwareutils/bmc/access.go
@@ -20,7 +20,7 @@ var factories = map[string]AccessDetailsFactory{}
 // with optional scheme extensions.
 //
 // RegisterFactory("bmcname", theFunc, []string{"http", "https"})
-// maps "bmcname", "bmcname+http", and "bmcname+https" to theFunc.
+// maps "bmcname", "bmcname+http", and "bmcname+https" to theFunc
 func RegisterFactory(name string, factory AccessDetailsFactory, schemes []string) {
 	factories[name] = factory
 
@@ -91,6 +91,7 @@ type AccessDetails interface {
 }
 
 func GetParsedURL(address string) (parsedURL *url.URL, err error) {
+
 	parsedURL, err = url.Parse(address)
 	if err != nil {
 		// We failed to parse the URL, but it may just be a host or
@@ -116,13 +117,14 @@ func GetParsedURL(address string) (parsedURL *url.URL, err error) {
 			parsedURL, err = url.Parse(strings.Replace(address, ":", "://", 1))
 			if err != nil {
 				return nil, errors.Wrap(err, "failed to parse BMC address information")
+
 			}
 		}
 		if parsedURL.Scheme == "" {
 			if parsedURL.Hostname() == "" {
 				// If there was no scheme at all, the hostname was
 				// interpreted as a path.
-				parsedURL, err = url.Parse("ipmi://" + address)
+				parsedURL, err = url.Parse(strings.Join([]string{"ipmi://", address}, ""))
 				if err != nil {
 					return nil, errors.Wrap(err, "failed to parse BMC address information")
 				}
@@ -141,6 +143,7 @@ func GetParsedURL(address string) (parsedURL *url.URL, err error) {
 // NewAccessDetails creates an AccessDetails structure from the URL
 // for a BMC.
 func NewAccessDetails(address string, disableCertificateVerification bool) (AccessDetails, error) {
+
 	if address == "" {
 		return nil, errors.New("missing BMC address")
 	}
@@ -159,6 +162,7 @@ func NewAccessDetails(address string, disableCertificateVerification bool) (Acce
 }
 
 func checkDNSValid(address string) error {
+
 	// Allowing empty BMC address
 	if address == "" {
 		return nil
diff --git a/pkg/hardwareutils/bmc/credentials.go b/pkg/hardwareutils/bmc/credentials.go
index da97fe3d..cbf28a50 100644
--- a/pkg/hardwareutils/bmc/credentials.go
+++ b/pkg/hardwareutils/bmc/credentials.go
@@ -6,7 +6,7 @@ type Credentials struct {
 	Password string
 }
 
-// Validate returns an error if the credentials are invalid.
+// Validate returns an error if the credentials are invalid
 func (creds Credentials) Validate() error {
 	if creds.Username == "" {
 		return &CredentialsValidationError{message: "Missing BMC connection detail 'username' in credentials"}
diff --git a/pkg/hardwareutils/bmc/errors.go b/pkg/hardwareutils/bmc/errors.go
index a1d96ff9..e018fa66 100644
--- a/pkg/hardwareutils/bmc/errors.go
+++ b/pkg/hardwareutils/bmc/errors.go
@@ -17,7 +17,7 @@ func (e UnknownBMCTypeError) Error() string {
 }
 
 // CredentialsValidationError is returned when the provided BMC credentials
-// are invalid (e.g. null).
+// are invalid (e.g. null)
 type CredentialsValidationError struct {
 	message string
 }
diff --git a/pkg/hardwareutils/bmc/ibmc.go b/pkg/hardwareutils/bmc/ibmc.go
index 24227b39..01e85d8d 100644
--- a/pkg/hardwareutils/bmc/ibmc.go
+++ b/pkg/hardwareutils/bmc/ibmc.go
@@ -6,14 +6,8 @@ import (
 	"strings"
 )
 
-const (
-	noRaid = "no-raid"
-	ibmc   = "ibmc"
-	ipxe   = "ipxe"
-)
-
 func init() {
-	RegisterFactory(ibmc, newIbmcAccessDetails, []string{"http", "https"})
+	RegisterFactory("ibmc", newIbmcAccessDetails, []string{"http", "https"})
 }
 
 func newIbmcAccessDetails(parsedURL *url.URL, disableCertificateVerification bool) (AccessDetails, error) {
@@ -45,7 +39,7 @@ func (a *ibmcAccessDetails) NeedsMAC() bool {
 }
 
 func (a *ibmcAccessDetails) Driver() string {
-	return ibmc
+	return "ibmc"
 }
 
 func (a *ibmcAccessDetails) DisableCertificateVerification() bool {
@@ -60,6 +54,7 @@ const ibmcDefaultScheme = "https"
 // expected to add any other information that might be needed (such as
 // the kernel and ramdisk locations).
 func (a *ibmcAccessDetails) DriverInfo(bmcCreds Credentials) map[string]interface{} {
+
 	ibmcAddress := []string{}
 	schemes := strings.Split(a.bmcType, "+")
 	if len(schemes) > 1 {
@@ -89,7 +84,7 @@ func (a *ibmcAccessDetails) BIOSInterface() string {
 }
 
 func (a *ibmcAccessDetails) BootInterface() string {
-	return ipxe
+	return "ipxe"
 }
 
 func (a *ibmcAccessDetails) FirmwareInterface() string {
@@ -97,15 +92,15 @@ func (a *ibmcAccessDetails) FirmwareInterface() string {
 }
 
 func (a *ibmcAccessDetails) ManagementInterface() string {
-	return ibmc
+	return "ibmc"
 }
 
 func (a *ibmcAccessDetails) PowerInterface() string {
-	return ibmc
+	return "ibmc"
 }
 
 func (a *ibmcAccessDetails) RAIDInterface() string {
-	return noRaid
+	return "no-raid"
 }
 
 func (a *ibmcAccessDetails) VendorInterface() string {
diff --git a/pkg/hardwareutils/bmc/idrac.go b/pkg/hardwareutils/bmc/idrac.go
index 3744c44a..bddc0267 100644
--- a/pkg/hardwareutils/bmc/idrac.go
+++ b/pkg/hardwareutils/bmc/idrac.go
@@ -5,14 +5,8 @@ import (
 	"strings"
 )
 
-const (
-	enabled  = "Enabled"
-	disabled = "Disabled"
-	idrac    = "idrac"
-)
-
 func init() {
-	RegisterFactory(idrac, newIDRACAccessDetails, []string{"http", "https"})
+	RegisterFactory("idrac", newIDRACAccessDetails, []string{"http", "https"})
 }
 
 func newIDRACAccessDetails(parsedURL *url.URL, disableCertificateVerification bool) (AccessDetails, error) {
@@ -44,7 +38,7 @@ func (a *iDracAccessDetails) NeedsMAC() bool {
 }
 
 func (a *iDracAccessDetails) Driver() string {
-	return idrac
+	return "idrac"
 }
 
 func (a *iDracAccessDetails) DisableCertificateVerification() bool {
@@ -85,7 +79,7 @@ func (a *iDracAccessDetails) BIOSInterface() string {
 }
 
 func (a *iDracAccessDetails) BootInterface() string {
-	return ipxe
+	return "ipxe"
 }
 
 func (a *iDracAccessDetails) FirmwareInterface() string {
@@ -130,9 +124,9 @@ func (a *iDracAccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (
 	var value string
 
 	if firmwareConfig.VirtualizationEnabled != nil {
-		value = disabled
+		value = "Disabled"
 		if *firmwareConfig.VirtualizationEnabled {
-			value = enabled
+			value = "Enabled"
 		}
 		settings = append(settings,
 			map[string]string{
@@ -143,9 +137,9 @@ func (a *iDracAccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (
 	}
 
 	if firmwareConfig.SimultaneousMultithreadingEnabled != nil {
-		value = disabled
+		value = "Disabled"
 		if *firmwareConfig.SimultaneousMultithreadingEnabled {
-			value = enabled
+			value = "Enabled"
 		}
 		settings = append(settings,
 			map[string]string{
@@ -156,9 +150,9 @@ func (a *iDracAccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (
 	}
 
 	if firmwareConfig.SriovEnabled != nil {
-		value = disabled
+		value = "Disabled"
 		if *firmwareConfig.SriovEnabled {
-			value = enabled
+			value = "Enabled"
 		}
 		settings = append(settings,
 			map[string]string{
diff --git a/pkg/hardwareutils/bmc/idrac_virtualmedia.go b/pkg/hardwareutils/bmc/idrac_virtualmedia.go
index 8f6f4887..79ffa57e 100644
--- a/pkg/hardwareutils/bmc/idrac_virtualmedia.go
+++ b/pkg/hardwareutils/bmc/idrac_virtualmedia.go
@@ -5,11 +5,6 @@ import (
 	"net/url"
 )
 
-const (
-	idracRedfish = "idrac-redfish"
-	redfish      = "redfish"
-)
-
 func init() {
 	schemes := []string{"http", "https"}
 	RegisterFactory("idrac-virtualmedia", newRedfishiDracVirtualMediaAccessDetails, schemes)
@@ -70,11 +65,11 @@ func (a *redfishiDracVirtualMediaAccessDetails) DriverInfo(bmcCreds Credentials)
 // iDrac Virtual Media Overrides
 
 func (a *redfishiDracVirtualMediaAccessDetails) Driver() string {
-	return idrac
+	return "idrac"
 }
 
 func (a *redfishiDracVirtualMediaAccessDetails) BIOSInterface() string {
-	return idracRedfish
+	return "idrac-redfish"
 }
 
 func (a *redfishiDracVirtualMediaAccessDetails) BootInterface() string {
@@ -82,24 +77,24 @@ func (a *redfishiDracVirtualMediaAccessDetails) BootInterface() string {
 }
 
 func (a *redfishiDracVirtualMediaAccessDetails) FirmwareInterface() string {
-	return redfish
+	return "redfish"
 }
 
 func (a *redfishiDracVirtualMediaAccessDetails) ManagementInterface() string {
-	return idracRedfish
+	return "idrac-redfish"
 }
 
 func (a *redfishiDracVirtualMediaAccessDetails) PowerInterface() string {
-	return idracRedfish
+	return "idrac-redfish"
 }
 
 func (a *redfishiDracVirtualMediaAccessDetails) RAIDInterface() string {
-	return idracRedfish
+	return "idrac-redfish"
 }
 
 func (a *redfishiDracVirtualMediaAccessDetails) VendorInterface() string {
 	// NOTE(dtantsur): the idrac hardware type defaults to WSMAN vendor, we need to use the Redfish implementation.
-	return idracRedfish
+	return "idrac-redfish"
 }
 
 func (a *redfishiDracVirtualMediaAccessDetails) SupportsSecureBoot() bool {
diff --git a/pkg/hardwareutils/bmc/ilo4.go b/pkg/hardwareutils/bmc/ilo4.go
index 993ee08a..6ccc68b1 100644
--- a/pkg/hardwareutils/bmc/ilo4.go
+++ b/pkg/hardwareutils/bmc/ilo4.go
@@ -64,6 +64,7 @@ func (a *iLOAccessDetails) DisableCertificateVerification() bool {
 // expected to add any other information that might be needed (such as
 // the kernel and ramdisk locations).
 func (a *iLOAccessDetails) DriverInfo(bmcCreds Credentials) map[string]interface{} {
+
 	result := map[string]interface{}{
 		"ilo_username": bmcCreds.Username,
 		"ilo_password": bmcCreds.Password,
@@ -88,8 +89,9 @@ func (a *iLOAccessDetails) BIOSInterface() string {
 func (a *iLOAccessDetails) BootInterface() string {
 	if a.useVirtualMedia {
 		return "ilo-virtual-media"
+	} else {
+		return "ilo-ipxe"
 	}
-	return "ilo-ipxe"
 }
 
 func (a *iLOAccessDetails) FirmwareInterface() string {
@@ -105,7 +107,7 @@ func (a *iLOAccessDetails) PowerInterface() string {
 }
 
 func (a *iLOAccessDetails) RAIDInterface() string {
-	return noRaid
+	return "no-raid"
 }
 
 func (a *iLOAccessDetails) VendorInterface() string {
@@ -132,9 +134,9 @@ func (a *iLOAccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (se
 	var value string
 
 	if firmwareConfig.VirtualizationEnabled != nil {
-		value = disabled
+		value = "Disabled"
 		if *firmwareConfig.VirtualizationEnabled {
-			value = enabled
+			value = "Enabled"
 		}
 		settings = append(settings,
 			map[string]string{
@@ -145,9 +147,9 @@ func (a *iLOAccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (se
 	}
 
 	if firmwareConfig.SimultaneousMultithreadingEnabled != nil {
-		value = disabled
+		value = "Disabled"
 		if *firmwareConfig.SimultaneousMultithreadingEnabled {
-			value = enabled
+			value = "Enabled"
 		}
 		settings = append(settings,
 			map[string]string{
@@ -158,9 +160,9 @@ func (a *iLOAccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (se
 	}
 
 	if firmwareConfig.SriovEnabled != nil {
-		value = disabled
+		value = "Disabled"
 		if *firmwareConfig.SriovEnabled {
-			value = enabled
+			value = "Enabled"
 		}
 		settings = append(settings,
 			map[string]string{
diff --git a/pkg/hardwareutils/bmc/ilo5.go b/pkg/hardwareutils/bmc/ilo5.go
index 5bb8de76..e79bf442 100644
--- a/pkg/hardwareutils/bmc/ilo5.go
+++ b/pkg/hardwareutils/bmc/ilo5.go
@@ -52,6 +52,7 @@ func (a *iLO5AccessDetails) DisableCertificateVerification() bool {
 // expected to add any other information that might be needed (such as
 // the kernel and ramdisk locations).
 func (a *iLO5AccessDetails) DriverInfo(bmcCreds Credentials) map[string]interface{} {
+
 	result := map[string]interface{}{
 		"ilo_username": bmcCreds.Username,
 		"ilo_password": bmcCreds.Password,
@@ -117,9 +118,9 @@ func (a *iLO5AccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (s
 	var value string
 
 	if firmwareConfig.VirtualizationEnabled != nil {
-		value = disabled
+		value = "Disabled"
 		if *firmwareConfig.VirtualizationEnabled {
-			value = enabled
+			value = "Enabled"
 		}
 		settings = append(settings,
 			map[string]string{
@@ -130,9 +131,9 @@ func (a *iLO5AccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (s
 	}
 
 	if firmwareConfig.SimultaneousMultithreadingEnabled != nil {
-		value = disabled
+		value = "Disabled"
 		if *firmwareConfig.SimultaneousMultithreadingEnabled {
-			value = enabled
+			value = "Enabled"
 		}
 		settings = append(settings,
 			map[string]string{
@@ -143,9 +144,9 @@ func (a *iLO5AccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (s
 	}
 
 	if firmwareConfig.SriovEnabled != nil {
-		value = disabled
+		value = "Disabled"
 		if *firmwareConfig.SriovEnabled {
-			value = enabled
+			value = "Enabled"
 		}
 		settings = append(settings,
 			map[string]string{
diff --git a/pkg/hardwareutils/bmc/ipmi.go b/pkg/hardwareutils/bmc/ipmi.go
index 1d665517..eb30a35f 100644
--- a/pkg/hardwareutils/bmc/ipmi.go
+++ b/pkg/hardwareutils/bmc/ipmi.go
@@ -94,7 +94,7 @@ func (a *ipmiAccessDetails) BIOSInterface() string {
 }
 
 func (a *ipmiAccessDetails) BootInterface() string {
-	return ipxe
+	return "ipxe"
 }
 
 func (a *ipmiAccessDetails) FirmwareInterface() string {
@@ -110,7 +110,7 @@ func (a *ipmiAccessDetails) PowerInterface() string {
 }
 
 func (a *ipmiAccessDetails) RAIDInterface() string {
-	return noRaid
+	return "no-raid"
 }
 
 func (a *ipmiAccessDetails) VendorInterface() string {
diff --git a/pkg/hardwareutils/bmc/irmc.go b/pkg/hardwareutils/bmc/irmc.go
index a3368d89..f87c7147 100644
--- a/pkg/hardwareutils/bmc/irmc.go
+++ b/pkg/hardwareutils/bmc/irmc.go
@@ -4,11 +4,6 @@ import (
 	"net/url"
 )
 
-const (
-	FalseStr = "False"
-	TrueStr  = "True"
-)
-
 func init() {
 	RegisterFactory("irmc", newIRMCAccessDetails, []string{})
 }
@@ -80,7 +75,7 @@ func (a *iRMCAccessDetails) BIOSInterface() string {
 }
 
 func (a *iRMCAccessDetails) BootInterface() string {
-	return ipxe
+	return "ipxe"
 }
 
 func (a *iRMCAccessDetails) FirmwareInterface() string {
@@ -123,9 +118,9 @@ func (a *iRMCAccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (s
 	var value string
 
 	if firmwareConfig.VirtualizationEnabled != nil {
-		value = FalseStr
+		value = "False"
 		if *firmwareConfig.VirtualizationEnabled {
-			value = TrueStr
+			value = "True"
 		}
 		settings = append(settings,
 			map[string]string{
@@ -136,9 +131,9 @@ func (a *iRMCAccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (s
 	}
 
 	if firmwareConfig.SimultaneousMultithreadingEnabled != nil {
-		value = FalseStr
+		value = "False"
 		if *firmwareConfig.SimultaneousMultithreadingEnabled {
-			value = TrueStr
+			value = "True"
 		}
 		settings = append(settings,
 			map[string]string{
@@ -149,9 +144,9 @@ func (a *iRMCAccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (s
 	}
 
 	if firmwareConfig.SriovEnabled != nil {
-		value = FalseStr
+		value = "False"
 		if *firmwareConfig.SriovEnabled {
-			value = TrueStr
+			value = "True"
 		}
 		settings = append(settings,
 			map[string]string{
diff --git a/pkg/hardwareutils/bmc/redfish.go b/pkg/hardwareutils/bmc/redfish.go
index 411d4157..7fccbf71 100644
--- a/pkg/hardwareutils/bmc/redfish.go
+++ b/pkg/hardwareutils/bmc/redfish.go
@@ -8,7 +8,7 @@ import (
 
 func init() {
 	schemes := []string{"http", "https"}
-	RegisterFactory(redfish, newRedfishAccessDetails, schemes)
+	RegisterFactory("redfish", newRedfishAccessDetails, schemes)
 	RegisterFactory("ilo5-redfish", newRedfishAccessDetails, schemes)
 	RegisterFactory("idrac-redfish", newRedfishiDracAccessDetails, schemes)
 }
@@ -58,7 +58,7 @@ func (a *redfishAccessDetails) NeedsMAC() bool {
 }
 
 func (a *redfishAccessDetails) Driver() string {
-	return redfish
+	return "redfish"
 }
 
 func (a *redfishAccessDetails) DisableCertificateVerification() bool {
@@ -102,13 +102,13 @@ func (a *redfishAccessDetails) BIOSInterface() string {
 	return ""
 }
 
-// That can be either pxe or redfish-virtual-media.
+// That can be either pxe or redfish-virtual-media
 func (a *redfishAccessDetails) BootInterface() string {
-	return ipxe
+	return "ipxe"
 }
 
 func (a *redfishAccessDetails) FirmwareInterface() string {
-	return redfish
+	return "redfish"
 }
 
 func (a *redfishAccessDetails) ManagementInterface() string {
@@ -120,7 +120,7 @@ func (a *redfishAccessDetails) PowerInterface() string {
 }
 
 func (a *redfishAccessDetails) RAIDInterface() string {
-	return redfish
+	return "redfish"
 }
 
 func (a *redfishAccessDetails) VendorInterface() string {
@@ -146,38 +146,38 @@ func (a *redfishAccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig)
 	return nil, nil
 }
 
-// iDrac Redfish Overrides.
+// iDrac Redfish Overrides
 func (a *redfishiDracAccessDetails) Driver() string {
-	return idrac
+	return "idrac"
 }
 
 func (a *redfishiDracAccessDetails) BIOSInterface() string {
-	return idracRedfish
+	return "idrac-redfish"
 }
 
 func (a *redfishiDracAccessDetails) BootInterface() string {
-	return ipxe
+	return "ipxe"
 }
 
 func (a *redfishiDracAccessDetails) FirmwareInterface() string {
-	return redfish
+	return "redfish"
 }
 
 func (a *redfishiDracAccessDetails) ManagementInterface() string {
-	return ipxe
+	return "idrac-redfish"
 }
 
 func (a *redfishiDracAccessDetails) PowerInterface() string {
-	return idracRedfish
+	return "idrac-redfish"
 }
 
 func (a *redfishiDracAccessDetails) RAIDInterface() string {
-	return idracRedfish
+	return "idrac-redfish"
 }
 
 func (a *redfishiDracAccessDetails) VendorInterface() string {
 	// NOTE(dtantsur): the idrac hardware type defaults to WSMAN vendor, we need to use the Redfish implementation.
-	return idracRedfish
+	return "idrac-redfish"
 }
 
 func (a *redfishiDracAccessDetails) BuildBIOSSettings(firmwareConfig *FirmwareConfig) (settings []map[string]string, err error) {
diff --git a/pkg/hardwareutils/bmc/redfish_virtualmedia.go b/pkg/hardwareutils/bmc/redfish_virtualmedia.go
index 3e46626e..41a5f4b9 100644
--- a/pkg/hardwareutils/bmc/redfish_virtualmedia.go
+++ b/pkg/hardwareutils/bmc/redfish_virtualmedia.go
@@ -40,7 +40,7 @@ func (a *redfishVirtualMediaAccessDetails) NeedsMAC() bool {
 }
 
 func (a *redfishVirtualMediaAccessDetails) Driver() string {
-	return redfish
+	return "redfish"
 }
 
 func (a *redfishVirtualMediaAccessDetails) DisableCertificateVerification() bool {
@@ -76,7 +76,7 @@ func (a *redfishVirtualMediaAccessDetails) BootInterface() string {
 }
 
 func (a *redfishVirtualMediaAccessDetails) FirmwareInterface() string {
-	return redfish
+	return "redfish"
 }
 
 func (a *redfishVirtualMediaAccessDetails) ManagementInterface() string {
@@ -88,7 +88,7 @@ func (a *redfishVirtualMediaAccessDetails) PowerInterface() string {
 }
 
 func (a *redfishVirtualMediaAccessDetails) RAIDInterface() string {
-	return redfish
+	return "redfish"
 }
 
 func (a *redfishVirtualMediaAccessDetails) VendorInterface() string {
diff --git a/pkg/hardwareutils/go.mod b/pkg/hardwareutils/go.mod
index d00b164b..7a76a477 100644
--- a/pkg/hardwareutils/go.mod
+++ b/pkg/hardwareutils/go.mod
@@ -1,5 +1,5 @@
 module github.com/metal3-io/baremetal-operator/pkg/hardwareutils
 
-go 1.21
+go 1.20
 
 require github.com/pkg/errors v0.9.1
diff --git a/pkg/provisioner/demo/demo.go b/pkg/provisioner/demo/demo.go
index cf82e879..edc5a91e 100644
--- a/pkg/provisioner/demo/demo.go
+++ b/pkg/provisioner/demo/demo.go
@@ -14,6 +14,8 @@ import (
 )
 
 var log = logz.New().WithName("provisioner").WithName("demo")
+var deprovisionRequeueDelay = time.Second * 10
+var provisionRequeueDelay = time.Second * 10
 
 const (
 	// RegistrationErrorHost is a host that fails the registration
@@ -248,8 +250,38 @@ func (p *demoProvisioner) Provision(_ provisioner.ProvisionData, _ bool) (result
 // multiple times, and should return true for its dirty flag until the
 // deprovisioning operation is completed.
 func (p *demoProvisioner) Deprovision(_ bool) (result provisioner.Result, err error) {
-	p.log.Info("deprovisioning host")
-	return result, nil
+	hostName := p.objectMeta.Name
+	switch hostName {
+	default:
+		return result, nil
+	}
+
+	// p.log.Info("ensuring host is removed")
+
+	// result.RequeueAfter = deprovisionRequeueDelay
+
+	// // NOTE(dhellmann): In order to simulate a multi-step process,
+	// // modify some of the status data structures. This is likely not
+	// // necessary once we really have Demo doing the deprovisioning
+	// // and we can monitor it's status.
+
+	// if p.host.Status.HardwareDetails != nil {
+	// 	p.publisher("DeprovisionStarted", "Image deprovisioning started")
+	// 	p.log.Info("clearing hardware details")
+	// 	p.host.Status.HardwareDetails = nil
+	// 	result.Dirty = true
+	// 	return result, nil
+	// }
+
+	// if p.host.Status.Provisioning.ID != "" {
+	// 	p.log.Info("clearing provisioning id")
+	// 	p.host.Status.Provisioning.ID = ""
+	// 	result.Dirty = true
+	// 	return result, nil
+	// }
+
+	// p.publisher("DeprovisionComplete", "Image deprovisioning completed")
+	// return result, nil
 }
 
 // Delete removes the host from the provisioning system. It may be
@@ -273,18 +305,44 @@ func (p *demoProvisioner) Detach() (result provisioner.Result, err error) {
 // PowerOn ensures the server is powered on independently of any image
 // provisioning operation.
 func (p *demoProvisioner) PowerOn(_ bool) (result provisioner.Result, err error) {
-	p.log.Info("powering on host")
-	return result, nil
+	hostName := p.objectMeta.Name
+	switch hostName {
+	default:
+		return result, nil
+	}
+
+	// p.log.Info("ensuring host is powered on")
+
+	// if !p.host.Status.PoweredOn {
+	// 	p.host.Status.PoweredOn = true
+	// 	result.Dirty = true
+	// 	return result, nil
+	// }
+
+	// return result, nil
 }
 
 // PowerOff ensures the server is powered off independently of any image
 // provisioning operation.
 func (p *demoProvisioner) PowerOff(_ metal3api.RebootMode, _ bool) (result provisioner.Result, err error) {
-	p.log.Info("powering off host")
-	return result, nil
+	hostName := p.objectMeta.Name
+	switch hostName {
+	default:
+		return result, nil
+	}
+
+	// p.log.Info("ensuring host is powered off")
+
+	// if p.host.Status.PoweredOn {
+	// 	p.host.Status.PoweredOn = false
+	// 	result.Dirty = true
+	// 	return result, nil
+	// }
+
+	// return result, nil
 }
 
-// TryInit always returns true for the demo provisioner.
+// TryInit always returns true for the demo provisioner
 func (p *demoProvisioner) TryInit() (result bool, err error) {
 	return true, nil
 }
diff --git a/pkg/provisioner/fixture/fixture.go b/pkg/provisioner/fixture/fixture.go
index 693c993d..1d43c6bc 100644
--- a/pkg/provisioner/fixture/fixture.go
+++ b/pkg/provisioner/fixture/fixture.go
@@ -325,7 +325,7 @@ func (p *fixtureProvisioner) PowerOff(_ metal3api.RebootMode, _ bool) (result pr
 	return result, nil
 }
 
-// TryInit returns the current availability status of the provisioner.
+// TryInit returns the current availability status of the provisioner
 func (p *fixtureProvisioner) TryInit() (result bool, err error) {
 	p.log.Info("checking provisioner status")
 
diff --git a/pkg/provisioner/ironic/clients/features.go b/pkg/provisioner/ironic/clients/features.go
index 888c7a21..b98cc65c 100644
--- a/pkg/provisioner/ironic/clients/features.go
+++ b/pkg/provisioner/ironic/clients/features.go
@@ -18,7 +18,7 @@ type AvailableFeatures struct {
 // conservative when updating this value since doing so unconditionally breaks
 // operators of older Ironic, even if the feature we need is optional.
 // Update docs/configuration.md when updating the version.
-// Version 1.81 allows retrival of Node inventory.
+// Version 1.81 allows retrival of Node inventory
 const baseline = "1.81"
 
 func GetAvailableFeatures(client *gophercloud.ServiceClient) (features AvailableFeatures, err error) {
@@ -28,7 +28,7 @@ func GetAvailableFeatures(client *gophercloud.ServiceClient) (features Available
 	}
 
 	if mvs.MaxMajor != 1 || mvs.MaxMinor < 81 {
-		err = fmt.Errorf("ironic API 1.81 or newer is required, got %d.%d", mvs.MaxMajor, mvs.MaxMinor)
+		err = fmt.Errorf("Ironic API 1.81 or newer is required, got %d.%d", mvs.MaxMajor, mvs.MaxMinor)
 		return
 	}
 
diff --git a/pkg/provisioner/ironic/dependencies.go b/pkg/provisioner/ironic/dependencies.go
index c1c62e90..72643a8e 100644
--- a/pkg/provisioner/ironic/dependencies.go
+++ b/pkg/provisioner/ironic/dependencies.go
@@ -7,7 +7,7 @@ import (
 	"github.com/metal3-io/baremetal-operator/pkg/provisioner/ironic/clients"
 )
 
-// TryInit checks if the provisioning backend is available.
+// TryInit checks if the provisioning backend is available
 func (p *ironicProvisioner) TryInit() (ready bool, err error) {
 	p.debugLog.Info("verifying ironic provisioner dependencies")
 
diff --git a/pkg/provisioner/ironic/devicehints/devicehints.go b/pkg/provisioner/ironic/devicehints/devicehints.go
index db575c2d..e1f68960 100644
--- a/pkg/provisioner/ironic/devicehints/devicehints.go
+++ b/pkg/provisioner/ironic/devicehints/devicehints.go
@@ -49,9 +49,9 @@ func MakeHintMap(source *metal3api.RootDeviceHints) map[string]string {
 	}
 	switch {
 	case source.Rotational == nil:
-	case *source.Rotational:
+	case *source.Rotational == true:
 		hints["rotational"] = "true"
-	case !*source.Rotational:
+	case *source.Rotational == false:
 		hints["rotational"] = "false"
 	}
 
diff --git a/pkg/provisioner/ironic/ironic.go b/pkg/provisioner/ironic/ironic.go
index 190e54f5..75aaed4b 100644
--- a/pkg/provisioner/ironic/ironic.go
+++ b/pkg/provisioner/ironic/ironic.go
@@ -506,7 +506,10 @@ func (p *ironicProvisioner) ValidateManagementAccess(data provisioner.Management
 	if !success {
 		return
 	}
-
+	// ironicNode, err = nodes.Get(p.client, p.status.ID).Extract()
+	// if err != nil {
+	// 	return result, errors.Wrap(err, "failed to get provisioning state in ironic")
+	// }
 	p.log.Info("current provision state",
 		"lastError", ironicNode.LastError,
 		"current", ironicNode.ProvisionState,
diff --git a/tools/run_local_ironic.sh b/tools/run_local_ironic.sh
index 17c0e168..4ffa75de 100755
--- a/tools/run_local_ironic.sh
+++ b/tools/run_local_ironic.sh
@@ -39,10 +39,6 @@ MARIADB_CACERT_FILE="${MARIADB_CACERT_FILE:-}"
 MARIADB_CERT_FILE="${MARIADB_CERT_FILE:-}"
 MARIADB_KEY_FILE="${MARIADB_KEY_FILE:-}"
 
-IPXE_CACERT_FILE="${IPXE_CACERT_FILE:-}"
-IPXE_CERT_FILE="${IPXE_CERT_FILE:-}"
-IPXE_KEY_FILE="${IPXE_KEY_FILE:-}"
-
 # Variables used to configure IPA handling
 IPA_DOWNLOAD_ENABLED="${IPA_DOWNLOAD_ENABLED:-true}"
 USE_LOCAL_IPA="${USE_LOCAL_IPA:-false}"
@@ -153,46 +149,36 @@ fi
 
 CERTS_MOUNTS=""
 
-if [ -r "$IRONIC_CACERT_FILE" ]; then
+if [ -n "$IRONIC_CACERT_FILE" ]; then
      CERTS_MOUNTS="-v ${IRONIC_CACERT_FILE}:/certs/ca/ironic/tls.crt "
 fi
 
-if [ -r "$IRONIC_CERT_FILE" ]; then
+if [ -n "$IRONIC_CERT_FILE" ]; then
      CERTS_MOUNTS="${CERTS_MOUNTS} -v ${IRONIC_CERT_FILE}:/certs/ironic/tls.crt "
 fi
-if [ -r "$IRONIC_KEY_FILE" ]; then
+if [ -n "$IRONIC_KEY_FILE" ]; then
      CERTS_MOUNTS="${CERTS_MOUNTS} -v ${IRONIC_KEY_FILE}:/certs/ironic/tls.key "
 fi
-if [ -r "$IRONIC_INSPECTOR_CACERT_FILE" ]; then
+if [ -n "$IRONIC_INSPECTOR_CACERT_FILE" ]; then
      CERTS_MOUNTS="${CERTS_MOUNTS} -v ${IRONIC_INSPECTOR_CACERT_FILE}:/certs/ca/ironic-inspector/tls.crt "
 fi
-if [ -r "$IRONIC_INSPECTOR_CERT_FILE" ]; then
+if [ -n "$IRONIC_INSPECTOR_CERT_FILE" ]; then
      CERTS_MOUNTS="${CERTS_MOUNTS} -v ${IRONIC_INSPECTOR_CERT_FILE}:/certs/ironic-inspector/tls.crt "
 fi
-if [ -r "$IRONIC_INSPECTOR_KEY_FILE" ]; then
+if [ -n "$IRONIC_INSPECTOR_KEY_FILE" ]; then
      CERTS_MOUNTS="${CERTS_MOUNTS} -v ${IRONIC_INSPECTOR_KEY_FILE}:/certs/ironic-inspector/tls.key "
 fi
 
-if [ -r "$MARIADB_CACERT_FILE" ]; then
+if [ -n "$MARIADB_CACERT_FILE" ]; then
      CERTS_MOUNTS="${CERTS_MOUNTS} -v ${MARIADB_CACERT_FILE}:/certs/ca/mariadb/tls.crt "
 fi
-if [ -r "$MARIADB_CERT_FILE" ]; then
+if [ -n "$MARIADB_CERT_FILE" ]; then
      CERTS_MOUNTS="${CERTS_MOUNTS} -v ${MARIADB_CERT_FILE}:/certs/mariadb/tls.crt "
 fi
-if [ -r "$MARIADB_KEY_FILE" ]; then
+if [ -n "$MARIADB_KEY_FILE" ]; then
      CERTS_MOUNTS="${CERTS_MOUNTS} -v ${MARIADB_KEY_FILE}:/certs/mariadb/tls.key "
 fi
 
-if [[ -r "${IPXE_CACERT_FILE}" ]]; then
-     CERTS_MOUNTS="${CERTS_MOUNTS} -v ${IPXE_CACERT_FILE}:/certs/ca/ipxe/tls.crt "
-fi
-if [[ -r "${IPXE_CERT_FILE}" ]]; then
-     CERTS_MOUNTS="${CERTS_MOUNTS} -v ${IPXE_CERT_FILE}:/certs/ipxe/tls.crt "
-fi
-if [[ -r "${IPXE_KEY_FILE}" ]]; then
-     CERTS_MOUNTS="${CERTS_MOUNTS} -v ${IPXE_KEY_FILE}:/certs/ipxe/tls.key "
-fi
-
 BASIC_AUTH_MOUNTS=""
 IRONIC_HTPASSWD=""
 if [ -n "$IRONIC_USERNAME" ]; then
@@ -264,7 +250,7 @@ fi
 # https://github.com/metal3-io/ironic-image/blob/main/scripts/rundnsmasq
 # shellcheck disable=SC2086
 sudo "${CONTAINER_RUNTIME}" run -d --net host --privileged --name dnsmasq \
-     ${POD} ${CERTS_MOUNTS} --env-file "${IRONIC_DATA_DIR}/ironic-vars.env" \
+     ${POD} --env-file "${IRONIC_DATA_DIR}/ironic-vars.env" \
      -v "$IRONIC_DATA_DIR:/shared" --entrypoint /bin/rundnsmasq "${IRONIC_IMAGE}"
 
 # See this file for env vars you can set, like IP, DHCP_RANGE, INTERFACE


Test patch:
diff --git a/apis/metal3.io/v1alpha1/baremetalhost_types_test.go b/apis/metal3.io/v1alpha1/baremetalhost_types_test.go
index 7ee7f7bb..815dccdc 100644
--- a/apis/metal3.io/v1alpha1/baremetalhost_types_test.go
+++ b/apis/metal3.io/v1alpha1/baremetalhost_types_test.go
@@ -10,6 +10,7 @@ import (
 )
 
 func TestHostNeedsHardwareInspection(t *testing.T) {
+
 	testCases := []struct {
 		Scenario string
 		Host     BareMetalHost
diff --git a/apis/metal3.io/v1alpha1/hostfirmwarecomponents_types_test.go b/apis/metal3.io/v1alpha1/hostfirmwarecomponents_types_test.go
index e3b3ab85..4b8e6ea6 100644
--- a/apis/metal3.io/v1alpha1/hostfirmwarecomponents_types_test.go
+++ b/apis/metal3.io/v1alpha1/hostfirmwarecomponents_types_test.go
@@ -65,7 +65,7 @@ func TestValidateHostFirmwareComponents(t *testing.T) {
 					LastTransitionTime: metav1.NewTime(time.Now()),
 				},
 			},
-			ExpectedError: "component nic is invalid, only 'bmc' or 'bios' are allowed as update names",
+			ExpectedError: "Component nic is invalid, only 'bmc' or 'bios' are allowed as update names",
 		},
 	} {
 		t.Run(tc.Scenario, func(t *testing.T) {
diff --git a/apis/metal3.io/v1alpha1/hostfirmwaresettings_types_test.go b/apis/metal3.io/v1alpha1/hostfirmwaresettings_types_test.go
index fc2f78b6..40463267 100644
--- a/apis/metal3.io/v1alpha1/hostfirmwaresettings_types_test.go
+++ b/apis/metal3.io/v1alpha1/hostfirmwaresettings_types_test.go
@@ -10,6 +10,7 @@ import (
 )
 
 func TestValidateSetting(t *testing.T) {
+
 	lower_bound := 1
 	upper_bound := 20
 	min_length := 1
diff --git a/config/overlays/e2e-release-0.3/ironic.env b/config/overlays/e2e-release-0.3/ironic.env
deleted file mode 100644
index 786453ee..00000000
--- a/config/overlays/e2e-release-0.3/ironic.env
+++ /dev/null
@@ -1,10 +0,0 @@
-HTTP_PORT=6180
-PROVISIONING_IP=192.168.222.199
-DEPLOY_KERNEL_URL=http://192.168.222.199:6180/images/ironic-python-agent.kernel
-DEPLOY_RAMDISK_URL=http://192.168.222.199:6180/images/ironic-python-agent.initramfs
-IRONIC_ENDPOINT=https://192.168.222.199:6385/v1/
-IRONIC_INSPECTOR_ENDPOINT=https://192.168.222.199:5050/v1/
-CACHEURL=http://192.168.222.199/images
-IRONIC_FAST_TRACK=true
-IRONIC_KERNEL_PARAMS=console=ttyS0
-IRONIC_INSPECTOR_VLAN_INTERFACES=all
diff --git a/config/overlays/e2e-release-0.3/kustomization.yaml b/config/overlays/e2e-release-0.3/kustomization.yaml
deleted file mode 100644
index f1afbb11..00000000
--- a/config/overlays/e2e-release-0.3/kustomization.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-namespace: baremetal-operator-system
-resources:
-- https://github.com/metal3-io/baremetal-operator/config/tls?ref=release-0.3
-components:
-- ../../components/basic-auth
-configMapGenerator:
-- name: ironic
-  behavior: merge
-  envs:
-  - ironic.env
-patches:
-- patch: |
-    # Don't try to pull again the pre-loaded image
-    - op: replace
-      path: /spec/template/spec/containers/0/imagePullPolicy
-      value: IfNotPresent
-  target:
-    kind: Deployment
-    name: controller-manager
-images:
-- name: quay.io/metal3-io/baremetal-operator
-  newTag: release-0.3
-# We cannot use suffix hashes since the kustomizations we build on
-# cannot be aware of what suffixes we add.
-generatorOptions:
-  disableNameSuffixHash: true
-# NOTE: These credentials are generated automatically in hack/ci-e2e.sh
-secretGenerator:
-- name: ironic-credentials
-  files:
-  - username=ironic-username
-  - password=ironic-password
-- name: ironic-inspector-credentials
-  files:
-  - username=ironic-inspector-username
-  - password=ironic-inspector-password
diff --git a/config/overlays/e2e-release-0.4/kustomization.yaml b/config/overlays/e2e-release-0.4/kustomization.yaml
index b0759b25..3223ef59 100644
--- a/config/overlays/e2e-release-0.4/kustomization.yaml
+++ b/config/overlays/e2e-release-0.4/kustomization.yaml
@@ -2,14 +2,17 @@ apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
 namespace: baremetal-operator-system
 resources:
-- https://github.com/metal3-io/baremetal-operator/config/tls?ref=release-0.4
+  - https://github.com/metal3-io/baremetal-operator/config/tls?ref=release-0.4
+
 components:
-- ../../components/basic-auth
+  - ../../components/basic-auth
+
 configMapGenerator:
 - name: ironic
   behavior: merge
   envs:
   - ironic.env
+
 patches:
 - patch: |
     # Don't try to pull again the pre-loaded image
@@ -19,20 +22,24 @@ patches:
   target:
     kind: Deployment
     name: controller-manager
+
 images:
 - name: quay.io/metal3-io/baremetal-operator
   newTag: release-0.4
+
 # We cannot use suffix hashes since the kustomizations we build on
 # cannot be aware of what suffixes we add.
 generatorOptions:
   disableNameSuffixHash: true
+
 # NOTE: These credentials are generated automatically in hack/ci-e2e.sh
 secretGenerator:
-- name: ironic-credentials
-  files:
-  - username=ironic-username
-  - password=ironic-password
-- name: ironic-inspector-credentials
-  files:
-  - username=ironic-inspector-username
-  - password=ironic-inspector-password
+  - name: ironic-credentials
+    files:
+    - username=ironic-username
+    - password=ironic-password
+  - name: ironic-inspector-credentials
+    files:
+    - username=ironic-inspector-username
+    - password=ironic-inspector-password
+
diff --git a/config/overlays/e2e-release-0.5/ironic.env b/config/overlays/e2e-release-0.5/ironic.env
deleted file mode 100644
index 24c556e1..00000000
--- a/config/overlays/e2e-release-0.5/ironic.env
+++ /dev/null
@@ -1,9 +0,0 @@
-HTTP_PORT=6180
-PROVISIONING_IP=192.168.222.199
-DEPLOY_KERNEL_URL=http://192.168.222.199:6180/images/ironic-python-agent.kernel
-DEPLOY_RAMDISK_URL=http://192.168.222.199:6180/images/ironic-python-agent.initramfs
-IRONIC_ENDPOINT=https://192.168.222.199:6385/v1/
-CACHEURL=http://192.168.222.199/images
-IRONIC_FAST_TRACK=true
-IRONIC_KERNEL_PARAMS=console=ttyS0
-IRONIC_INSPECTOR_VLAN_INTERFACES=all
diff --git a/config/overlays/e2e-release-0.5/kustomization.yaml b/config/overlays/e2e-release-0.5/kustomization.yaml
deleted file mode 100644
index 7a37de37..00000000
--- a/config/overlays/e2e-release-0.5/kustomization.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-namespace: baremetal-operator-system
-resources:
-- https://github.com/metal3-io/baremetal-operator/config/overlays/basic-auth_tls?ref=release-0.5
-configMapGenerator:
-- name: ironic
-  behavior: create
-  envs:
-  - ironic.env
-patches:
-- patch: |
-    # Don't try to pull again the pre-loaded image
-    - op: replace
-      path: /spec/template/spec/containers/0/imagePullPolicy
-      value: IfNotPresent
-  target:
-    kind: Deployment
-    name: controller-manager
-images:
-- name: quay.io/metal3-io/baremetal-operator
-  newTag: release-0.5
-# We cannot use suffix hashes since the kustomizations we build on
-# cannot be aware of what suffixes we add.
-generatorOptions:
-  disableNameSuffixHash: true
-# NOTE: These credentials are generated automatically in hack/ci-e2e.sh
-secretGenerator:
-- name: ironic-credentials
-  files:
-  - username=ironic-username
-  - password=ironic-password
-- name: ironic-inspector-credentials
-  files:
-  - username=ironic-inspector-username
-  - password=ironic-inspector-password
diff --git a/controllers/metal3.io/host_config_data_test.go b/controllers/metal3.io/host_config_data_test.go
index f763a6e8..b80d3e1b 100644
--- a/controllers/metal3.io/host_config_data_test.go
+++ b/controllers/metal3.io/host_config_data_test.go
@@ -2,6 +2,7 @@ package controllers
 
 import (
 	"context"
+	goctx "context"
 	"encoding/base64"
 	"fmt"
 	"testing"
@@ -335,10 +336,10 @@ func TestProvisionWithHostConfig(t *testing.T) {
 			tc.Host.Spec.Online = true
 
 			c := fakeclient.NewClientBuilder().WithObjects(tc.Host).Build()
-			c.Create(context.TODO(), testBMCSecret)
-			c.Create(context.TODO(), tc.UserDataSecret)
-			c.Create(context.TODO(), tc.NetworkDataSecret)
-			c.Create(context.TODO(), tc.PreprovNetworkDataSecret)
+			c.Create(goctx.TODO(), testBMCSecret)
+			c.Create(goctx.TODO(), tc.UserDataSecret)
+			c.Create(goctx.TODO(), tc.NetworkDataSecret)
+			c.Create(goctx.TODO(), tc.PreprovNetworkDataSecret)
 			baselog := ctrl.Log.WithName("controllers").WithName("BareMetalHost")
 			hcd := &hostConfigData{
 				host:          tc.Host,
diff --git a/hack/ci-e2e.sh b/hack/ci-e2e.sh
index aecfb605..7af7e41d 100755
--- a/hack/ci-e2e.sh
+++ b/hack/ci-e2e.sh
@@ -113,7 +113,7 @@ docker run --name image-server-e2e -d \
 ssh-keygen -t ed25519 -f "${IMAGE_DIR}/ssh_testkey" -q -N ""
 
 # Generate credentials
-BMO_OVERLAYS=("${REPO_ROOT}/config/overlays/e2e" "${REPO_ROOT}/config/overlays/e2e-release-0.4" "${REPO_ROOT}/config/overlays/e2e-release-0.5")
+BMO_OVERLAY="${REPO_ROOT}/config/overlays/e2e"
 IRONIC_OVERLAY="${REPO_ROOT}/ironic-deployment/overlays/e2e"
 
 IRONIC_USERNAME="$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 12 | head -n 1)"
@@ -121,12 +121,16 @@ IRONIC_PASSWORD="$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 12 | head -n 1)"
 IRONIC_INSPECTOR_USERNAME="$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 12 | head -n 1)"
 IRONIC_INSPECTOR_PASSWORD="$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 12 | head -n 1)"
 
-for overlay in "${BMO_OVERLAYS[@]}"; do
-  echo "${IRONIC_USERNAME}" > "${overlay}/ironic-username"
-  echo "${IRONIC_PASSWORD}" > "${overlay}/ironic-password"
-  echo "${IRONIC_INSPECTOR_USERNAME}" > "${overlay}/ironic-inspector-username"
-  echo "${IRONIC_INSPECTOR_PASSWORD}" > "${overlay}/ironic-inspector-password"
-done
+echo "${IRONIC_USERNAME}" > "${BMO_OVERLAY}/ironic-username"
+echo "${IRONIC_PASSWORD}" > "${BMO_OVERLAY}/ironic-password"
+echo "${IRONIC_INSPECTOR_USERNAME}" > "${BMO_OVERLAY}/ironic-inspector-username"
+echo "${IRONIC_INSPECTOR_PASSWORD}" > "${BMO_OVERLAY}/ironic-inspector-password"
+
+BMO_UPGRADE_FROM_OVERLAY="${REPO_ROOT}/config/overlays/e2e-release-0.4"
+echo "${IRONIC_USERNAME}" > "${BMO_UPGRADE_FROM_OVERLAY}/ironic-username"
+echo "${IRONIC_PASSWORD}" > "${BMO_UPGRADE_FROM_OVERLAY}/ironic-password"
+echo "${IRONIC_INSPECTOR_USERNAME}" > "${BMO_UPGRADE_FROM_OVERLAY}/ironic-inspector-username"
+echo "${IRONIC_INSPECTOR_PASSWORD}" > "${BMO_UPGRADE_FROM_OVERLAY}/ironic-inspector-password"
 
 envsubst < "${REPO_ROOT}/ironic-deployment/components/basic-auth/ironic-auth-config-tpl" > \
   "${IRONIC_OVERLAY}/ironic-auth-config"
diff --git a/pkg/hardwareutils/bmc/access_test.go b/pkg/hardwareutils/bmc/access_test.go
index 420b57c6..2ed2a319 100644
--- a/pkg/hardwareutils/bmc/access_test.go
+++ b/pkg/hardwareutils/bmc/access_test.go
@@ -1185,7 +1185,7 @@ func TestDriverInfo(t *testing.T) {
 				t.Fatalf("unexpected parse error: %v", err)
 			}
 			di := acc.DriverInfo(Credentials{})
-			// If a key is present when it should not, this will catch it
+			//If a key is present when it should not, this will catch it
 			if len(di) != len(tc.expects) {
 				t.Fatalf("Number of items do not match: %v and %v, %#v", len(di),
 					len(tc.expects), di)
diff --git a/pkg/provisioner/ironic/testserver/ironic.go b/pkg/provisioner/ironic/testserver/ironic.go
index da1f4650..597d7756 100644
--- a/pkg/provisioner/ironic/testserver/ironic.go
+++ b/pkg/provisioner/ironic/testserver/ironic.go
@@ -13,8 +13,6 @@ import (
 )
 
 // IronicMock is a test server that implements Ironic's semantics.
-const v1node = "/v1/nodes/"
-
 type IronicMock struct {
 	*MockServer
 	CreatedNodes int
@@ -22,7 +20,6 @@ type IronicMock struct {
 
 // NewIronic builds an ironic mock server.
 func NewIronic(t *testing.T) *IronicMock {
-	t.Helper()
 	server := New(t, "ironic").AddDefaultResponse("/v1/?", "", http.StatusOK, versionedRootResult)
 	return &IronicMock{
 		MockServer:   server,
@@ -31,7 +28,6 @@ func NewIronic(t *testing.T) *IronicMock {
 }
 
 const validateResult = `{"boot": {"result": true}, "deploy": {"result": true}, "power": {"result": true}}`
-const maintenance = "/maintenance"
 
 // NOTE(dtantsur): the actual result is much longer, but we only potentially care about versions.
 const versionedRootResult = `
@@ -46,7 +42,7 @@ const versionedRootResult = `
   }
 }`
 
-// WithDefaultResponses sets a valid answer for all the API calls.
+// WithDefaultResponses sets a valid answer for all the API calls
 func (m *IronicMock) WithDefaultResponses() *IronicMock {
 	m.AddDefaultResponseJSON("/v1/nodes/{id}", "", http.StatusOK, nodes.Node{
 		UUID: "{id}",
@@ -68,7 +64,7 @@ func (m *IronicMock) Endpoint() string {
 	return m.MockServer.Endpoint()
 }
 
-// NotReady configures the server with an error response for /v1/ overriding the default response.
+// NotReady configures the server with an error response for /v1/ overriding the default response
 func (m *IronicMock) NotReady(errorCode int) *IronicMock {
 	m.ErrorResponse("/v1/", errorCode)
 	return m
@@ -112,30 +108,30 @@ func (m *IronicMock) buildURL(url string, method string) string {
 // Delete configures the server with a valid response for [DELETE] /v1/nodes/ on the
 // specific node id.
 func (m *IronicMock) Delete(id string) *IronicMock {
-	m.ResponseWithCode(m.buildURL(v1node+id, http.MethodDelete), "", http.StatusAccepted)
+	m.ResponseWithCode(m.buildURL("/v1/nodes/"+id, http.MethodDelete), "", http.StatusAccepted)
 	return m
 }
 
 // DeleteError configures the server with an error response for [DELETE] /v1/nodes/.
 func (m *IronicMock) DeleteError(id string, errorCode int) *IronicMock {
-	m.ResponseWithCode(m.buildURL(v1node+id, http.MethodDelete), "", errorCode)
+	m.ResponseWithCode(m.buildURL("/v1/nodes/"+id, http.MethodDelete), "", errorCode)
 	return m
 }
 
 // Node configures the server with a valid response for /v1/nodes/{name,uuid}.
 func (m *IronicMock) Node(node nodes.Node) *IronicMock {
 	if node.UUID != "" {
-		m.ResponseJSON(m.buildURL(v1node+node.UUID, http.MethodGet), node)
+		m.ResponseJSON(m.buildURL("/v1/nodes/"+node.UUID, http.MethodGet), node)
 	}
 	if node.Name != "" {
-		m.ResponseJSON(m.buildURL(v1node+node.Name, http.MethodGet), node)
+		m.ResponseJSON(m.buildURL("/v1/nodes/"+node.Name, http.MethodGet), node)
 	}
 	return m
 }
 
 // NodeUpdateError configures configures the server with an error response for [PATCH] /v1/nodes/{id}.
 func (m *IronicMock) NodeUpdateError(id string, errorCode int) *IronicMock {
-	m.ResponseWithCode(m.buildURL(v1node+id, http.MethodPatch), "", errorCode)
+	m.ResponseWithCode(m.buildURL("/v1/nodes/"+id, http.MethodPatch), "", errorCode)
 	return m
 }
 
@@ -143,17 +139,17 @@ func (m *IronicMock) NodeUpdateError(id string, errorCode int) *IronicMock {
 // for /v1/nodes/{name,uuid}.
 func (m *IronicMock) NodeUpdate(node nodes.Node) *IronicMock {
 	if node.UUID != "" {
-		m.ResponseJSON(m.buildURL(v1node+node.UUID, http.MethodPatch), node)
+		m.ResponseJSON(m.buildURL("/v1/nodes/"+node.UUID, http.MethodPatch), node)
 	}
 	if node.Name != "" {
-		m.ResponseJSON(m.buildURL(v1node+node.Name, http.MethodPatch), node)
+		m.ResponseJSON(m.buildURL("/v1/nodes/"+node.Name, http.MethodPatch), node)
 	}
 	return m
 }
 
 // GetLastNodeUpdateRequestFor returns the content of the last update request for the specified node.
 func (m *IronicMock) GetLastNodeUpdateRequestFor(id string) (updates []nodes.UpdateOperation) {
-	if bodyRaw, ok := m.GetLastRequestFor(v1node+id, http.MethodPatch); ok {
+	if bodyRaw, ok := m.GetLastRequestFor("/v1/nodes/"+id, http.MethodPatch); ok {
 		json.Unmarshal([]byte(bodyRaw), &updates)
 	}
 
@@ -162,7 +158,7 @@ func (m *IronicMock) GetLastNodeUpdateRequestFor(id string) (updates []nodes.Upd
 
 // GetLastNodeStatesProvisionUpdateRequestFor returns the content of the last provisioning request for the specified node.
 func (m *IronicMock) GetLastNodeStatesProvisionUpdateRequestFor(id string) (update nodes.ProvisionStateOpts) {
-	if bodyRaw, ok := m.GetLastRequestFor(v1node+id+"/states/provision", http.MethodPut); ok {
+	if bodyRaw, ok := m.GetLastRequestFor("/v1/nodes/"+id+"/states/provision", http.MethodPut); ok {
 		json.Unmarshal([]byte(bodyRaw), &update)
 	}
 
@@ -171,7 +167,7 @@ func (m *IronicMock) GetLastNodeStatesProvisionUpdateRequestFor(id string) (upda
 
 // NodeMaintenanceError configures configures the server with an error response for [PUT] /v1/nodes/{id}/maintenance.
 func (m *IronicMock) NodeMaintenanceError(id string, errorCode int) *IronicMock {
-	m.ResponseWithCode(m.buildURL(v1node+id+maintenance, http.MethodPut), "", errorCode)
+	m.ResponseWithCode(m.buildURL("/v1/nodes/"+id+"/maintenance", http.MethodPut), "", errorCode)
 	return m
 }
 
@@ -187,9 +183,9 @@ func (m *IronicMock) NodeMaintenance(node nodes.Node, expected bool) *IronicMock
 	}
 
 	if node.Name != "" {
-		url = m.buildURL(v1node+node.Name+maintenance, method)
+		url = m.buildURL("/v1/nodes/"+node.Name+"/maintenance", method)
 	} else {
-		url = m.buildURL(v1node+node.UUID+maintenance, method)
+		url = m.buildURL("/v1/nodes/"+node.UUID+"/maintenance", method)
 	}
 
 	m.ResponseWithCode(url, "{}", http.StatusAccepted)
@@ -197,7 +193,7 @@ func (m *IronicMock) NodeMaintenance(node nodes.Node, expected bool) *IronicMock
 }
 
 func (m *IronicMock) withNodeStatesProvision(nodeUUID string, method string) *IronicMock {
-	m.ResponseWithCode(m.buildURL(v1node+nodeUUID+"/states/provision", method), "{}", http.StatusAccepted)
+	m.ResponseWithCode(m.buildURL("/v1/nodes/"+nodeUUID+"/states/provision", method), "{}", http.StatusAccepted)
 	return m
 }
 
@@ -231,7 +227,6 @@ func (m *IronicMock) CreateNodes(callback NodeCreateCallback) *IronicMock {
 		if r.Method != http.MethodPost {
 			http.Error(w, fmt.Sprintf("%s not handled for %s", r.Method, r.URL),
 				http.StatusNotImplemented)
-			return
 		}
 
 		bodyRaw, err := io.ReadAll(r.Body)
@@ -270,7 +265,7 @@ func (m *IronicMock) CreateNodes(callback NodeCreateCallback) *IronicMock {
 }
 
 func (m *IronicMock) withNodeStatesPower(nodeUUID string, code int, method string) *IronicMock {
-	m.ResponseWithCode(m.buildURL(v1node+nodeUUID+"/states/power", method), "{}", code)
+	m.ResponseWithCode(m.buildURL("/v1/nodes/"+nodeUUID+"/states/power", method), "{}", code)
 	return m
 }
 
@@ -286,7 +281,7 @@ func (m *IronicMock) WithNodeStatesPowerUpdate(nodeUUID string, code int) *Ironi
 
 // WithNodeValidate configures the server with a valid response for /v1/nodes/<node>/validate.
 func (m *IronicMock) WithNodeValidate(nodeUUID string) *IronicMock {
-	m.ResponseWithCode(v1node+nodeUUID+"/validate", validateResult, http.StatusOK)
+	m.ResponseWithCode("/v1/nodes/"+nodeUUID+"/validate", validateResult, http.StatusOK)
 	return m
 }
 
@@ -307,7 +302,7 @@ func (m *IronicMock) Port(port ports.Port) *IronicMock {
 
 	address := url.QueryEscape(port.Address)
 
-	m.ResponseJSON(m.buildURL(v1node+port.NodeUUID+"/ports", http.MethodGet), resp)
+	m.ResponseJSON(m.buildURL("/v1/nodes/"+port.NodeUUID+"/ports", http.MethodGet), resp)
 	m.ResponseJSON(m.buildURL("/v1/ports", http.MethodGet), resp)
 	m.ResponseJSON(m.buildURL("/v1/ports?address="+address, http.MethodGet), resp)
 	m.ResponseJSON(m.buildURL("/v1/ports?address="+address+"&fields=node_uuid", http.MethodGet), resp)
@@ -385,8 +380,8 @@ func (m *IronicMock) BIOSSettings(nodeUUID string) *IronicMock {
 		Settings: settings,
 	}
 
-	m.ResponseJSON(m.buildURL(v1node+nodeUUID+"/bios", http.MethodGet), resp)
-	m.AddDefaultResponseJSON(v1node+nodeUUID, "", http.StatusOK, nodes.Node{
+	m.ResponseJSON(m.buildURL("/v1/nodes/"+nodeUUID+"/bios", http.MethodGet), resp)
+	m.AddDefaultResponseJSON("/v1/nodes/"+nodeUUID, "", http.StatusOK, nodes.Node{
 		UUID: nodeUUID,
 	})
 	return m
@@ -449,8 +444,8 @@ func (m *IronicMock) BIOSDetailSettings(nodeUUID string) *IronicMock {
 		Settings: settings,
 	}
 
-	m.ResponseJSON(m.buildURL(v1node+nodeUUID+"/bios", http.MethodGet), resp)
-	m.AddDefaultResponseJSON(v1node+nodeUUID, "", http.StatusOK, nodes.Node{
+	m.ResponseJSON(m.buildURL("/v1/nodes/"+nodeUUID+"/bios", http.MethodGet), resp)
+	m.AddDefaultResponseJSON("/v1/nodes/"+nodeUUID, "", http.StatusOK, nodes.Node{
 		UUID: nodeUUID,
 	})
 	return m
@@ -463,12 +458,12 @@ func (m *IronicMock) NoBIOS(nodeUUID string) *IronicMock {
 
 // WithInventory configures the server with a valid response for /v1/nodes/<node>/inventory.
 func (m *IronicMock) WithInventory(nodeUUID string, data nodes.InventoryData) *IronicMock {
-	m.ResponseJSON(v1node+nodeUUID+"/inventory", data)
+	m.ResponseJSON("/v1/nodes/"+nodeUUID+"/inventory", data)
 	return m
 }
 
 // WithInventoryFailed configures the server with an error response for /v1/nodes/<node>/inventory.
 func (m *IronicMock) WithInventoryFailed(nodeUUID string, errorCode int) *IronicMock {
-	m.ErrorResponse(v1node+nodeUUID+"/inventory", errorCode)
+	m.ErrorResponse("/v1/nodes/"+nodeUUID+"/inventory", errorCode)
 	return m
 }
diff --git a/pkg/provisioner/ironic/testserver/server.go b/pkg/provisioner/ironic/testserver/server.go
index 01f23091..d885281a 100644
--- a/pkg/provisioner/ironic/testserver/server.go
+++ b/pkg/provisioner/ironic/testserver/server.go
@@ -45,12 +45,14 @@ type simpleRequest struct {
 
 // MockServer is a simple http testing server.
 type MockServer struct {
-	t                 *testing.T
-	mux               *http.ServeMux
-	name              string
-	Requests          string
-	FullRequests      []simpleRequest
-	server            *httptest.Server
+	t            *testing.T
+	mux          *http.ServeMux
+	name         string
+	Requests     string
+	FullRequests []simpleRequest
+	server       *httptest.Server
+	errorCode    int
+
 	responsesByMethod map[string]map[string]response
 	defaultResponses  []defaultResponse
 }
@@ -221,24 +223,23 @@ func (m *MockServer) defaultHandler(w http.ResponseWriter, r *http.Request) {
 	method := r.Method
 
 	for _, response := range m.defaultResponses {
-		if response.method != "" && response.method != method {
-			continue
-		}
-		match := response.re.FindStringSubmatch(url)
-		if match == nil {
-			continue
-		}
+		if response.method == "" || response.method == method {
+			match := response.re.FindStringSubmatch(url)
+			if match == nil {
+				continue
+			}
 
-		m.t.Logf("%s: found default response for %s: {%d, %s}", m.name, url, response.code, response.payload)
-		payload := response.payload
-		for i, name := range response.re.SubexpNames() {
-			if i != 0 && name != "" {
-				payload = strings.ReplaceAll(payload, "{"+name+"}", match[i])
+			m.t.Logf("%s: found default response for %s: {%d, %s}", m.name, url, response.code, response.payload)
+			payload := response.payload
+			for i, name := range response.re.SubexpNames() {
+				if i != 0 && name != "" {
+					payload = strings.ReplaceAll(payload, "{"+name+"}", match[i])
+				}
 			}
-		}
 
-		m.sendData(w, r, response.code, payload)
-		return
+			m.sendData(w, r, response.code, payload)
+			return
+		}
 	}
 
 	m.t.Logf("%s: Cannot find any default response for [%s] %s", m.name, method, url)
diff --git a/test/e2e/bmc.go b/test/e2e/bmc.go
index 6bea16b5..d872eb2d 100644
--- a/test/e2e/bmc.go
+++ b/test/e2e/bmc.go
@@ -7,7 +7,7 @@ import (
 	"gopkg.in/yaml.v2"
 )
 
-// BMC defines a BMH to use in the tests.
+// BMC defines a BMH to use in the tests
 type BMC struct {
 	// BMC initial username
 	User string `yaml:"user,omitempty"`
@@ -22,7 +22,7 @@ type BMC struct {
 	// The IP address of the node
 	// Optional. Only needed if e2eConfig variable
 	// SSH_CHECK_PROVISIONED is true
-	IPAddress string `yaml:"ipAddress,omitempty"`
+	IpAddress string `yaml:"ipAddress,omitempty"`
 	// Optional. Only needed if e2eConfig variable
 	// SSH_CHECK_PROVISIONED is true
 	SSHPort string `yaml:"sshPort,omitempty"`
diff --git a/test/e2e/common.go b/test/e2e/common.go
index af84df27..cc5c520a 100644
--- a/test/e2e/common.go
+++ b/test/e2e/common.go
@@ -17,7 +17,7 @@ import (
 
 	v1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
-	k8serrors "k8s.io/apimachinery/pkg/api/errors"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
@@ -98,6 +98,7 @@ func (c *Config) Defaults() {
 // - Image should have name and loadBehavior be one of [mustload, tryload].
 // - Intervals should be valid ginkgo intervals.
 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 == "" {
@@ -211,7 +212,7 @@ func WaitForBmhDeleted(ctx context.Context, input WaitForBmhDeletedInput, interv
 		err := input.Client.Get(ctx, key, bmh)
 
 		// If BMH is not found, it's considered deleted, which is the desired outcome.
-		if k8serrors.IsNotFound(err) {
+		if apierrors.IsNotFound(err) {
 			return true
 		}
 		g.Expect(err).NotTo(HaveOccurred())
@@ -240,7 +241,7 @@ func WaitForNamespaceDeleted(ctx context.Context, input WaitForNamespaceDeletedI
 		key := client.ObjectKey{
 			Name: input.Namespace.Name,
 		}
-		return k8serrors.IsNotFound(input.Getter.Get(ctx, key, namespace))
+		return apierrors.IsNotFound(input.Getter.Get(ctx, key, namespace))
 	}, intervals...).Should(BeTrue())
 }
 
@@ -455,7 +456,7 @@ func (input *BuildAndApplyKustomizeInput) validate() error {
 }
 
 // BuildAndApplyKustomize takes input from BuildAndApplyKustomizeInput. It builds the provided kustomization
-// and apply it to the cluster provided by clusterProxy.
+// and apply it to the cluster provided by clusterProxy
 func BuildAndApplyKustomize(ctx context.Context, input *BuildAndApplyKustomizeInput) error {
 	Expect(input.validate()).To(BeNil())
 	var err error
diff --git a/test/e2e/config/fixture.yaml b/test/e2e/config/fixture.yaml
index a1380fe2..be34f04f 100644
--- a/test/e2e/config/fixture.yaml
+++ b/test/e2e/config/fixture.yaml
@@ -23,7 +23,7 @@ variables:
   UPGRADE_DEPLOY_IRONIC: "false"
   UPGRADE_DEPLOY_BMO: "true"
   UPGRADE_DEPLOY_CERT_MANAGER: "true"
-  UPGRADE_BMO_KUSTOMIZATION_FROM: "../../config/overlays/fixture-release-0.5"
+  UPGRADE_BMO_KUSTOMIZATION_FROM: "../../config/overlays/fixture-release-0.4"
 
   IMAGE_URL: "http://192.168.222.1/cirros-0.6.2-x86_64-disk.img"
   IMAGE_CHECKSUM: "c8fc807773e5354afe61636071771906"
@@ -48,3 +48,4 @@ intervals:
   default/wait-deleting: ["5s", "10ms"]
   default/wait-deleted: ["5s", "10ms"]
   default/wait-secret-deletion: ["5s", "10ms"]
+  default/wait-power-state: ["5s", "10ms"]
diff --git a/test/e2e/config/ironic.yaml b/test/e2e/config/ironic.yaml
index a04af65a..30cc5201 100644
--- a/test/e2e/config/ironic.yaml
+++ b/test/e2e/config/ironic.yaml
@@ -27,7 +27,7 @@ variables:
   UPGRADE_DEPLOY_IRONIC: "true"
   UPGRADE_DEPLOY_BMO: "true"
   UPGRADE_DEPLOY_CERT_MANAGER: "true"
-  UPGRADE_BMO_KUSTOMIZATION_FROM: "../../config/overlays/e2e-release-0.5"
+  UPGRADE_BMO_KUSTOMIZATION_FROM: "../../config/overlays/e2e-release-0.4"
 
   IMAGE_URL: "http://192.168.222.1/cirros-0.6.2-x86_64-disk.img"
   IMAGE_CHECKSUM: "c8fc807773e5354afe61636071771906"
@@ -42,14 +42,14 @@ intervals:
   inspection/wait-unmanaged: ["1m", "5s"]
   default/wait-registering: ["1m", "5s"]
   inspection/wait-registration-error: ["1m", "5s"]
-  external-inspection/wait-available: ["1m", "1s"]
+  external-inspection/wait-available: ["20s", "1s"]
   default/wait-inspecting: ["2m", "2s"]
   default/wait-available: ["10m", "1s"]
   default/wait-deployment: ["5m", "1s"]
   default/wait-namespace-deleted: ["10m", "1s"]
   ironic/wait-deployment: ["10m", "2s"]
   default/wait-power-state: ["10m", "100ms"]
-  default/wait-provisioning: ["1m", "1s"]
+  default/wait-provisioning: ["20s", "1s"]
   default/wait-provisioned: ["10m", "1s"]
   default/wait-deprovisioning: ["1m", "10ms"]
   default/wait-deleted: ["20s", "10ms"]
diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go
index dfeb7777..af80191f 100644
--- a/test/e2e/e2e_suite_test.go
+++ b/test/e2e/e2e_suite_test.go
@@ -27,7 +27,7 @@ var (
 	// configPath is the path to the e2e config file.
 	configPath string
 
-	// bmcConfigPath is the path to the file whose content is the list of bmcs used in the test.
+	// bmcConfigPath is the path to the file whose content is the list of bmcs used in the test
 	bmcConfigPath string
 
 	// useExistingCluster instructs the test to use the current cluster instead of creating a new one (default discovery rules apply).
@@ -36,7 +36,7 @@ var (
 	// e2eConfig to be used for this test, read from configPath.
 	e2eConfig *Config
 
-	// bmcs to be used for this test, read from bmcConfigPath.
+	// bmcs to be used for this test, read from bmcConfigPath
 	bmcs *[]BMC
 
 	// artifactFolder is the folder to store e2e test artifacts.
@@ -52,7 +52,7 @@ var (
 	// Please note that provisioning will be skipped if e2e.use-existing-cluster is provided.
 	clusterProvider bootstrap.ClusterProvider
 
-	// the BMC instance to use in a parallel test.
+	// the BMC instance to use in a parallel test
 	bmc BMC
 )
 
@@ -69,7 +69,7 @@ func TestE2e(t *testing.T) {
 	ctrl.SetLogger(klog.Background())
 
 	// ensure the artifacts folder exists
-	g.Expect(os.MkdirAll(artifactFolder, 0755)).To(Succeed(), "Invalid test suite argument. Can't create e2e.artifacts-folder %q", artifactFolder)
+	g.Expect(os.MkdirAll(artifactFolder, 0755)).To(Succeed(), "Invalid test suite argument. Can't create e2e.artifacts-folder %q", artifactFolder) //nolint:gosec
 
 	RegisterFailHandler(Fail)
 	RunSpecs(t, "E2e Suite")
diff --git a/test/e2e/live_iso_test.go b/test/e2e/live_iso_test.go
index 51f8b3d3..09f307f7 100644
--- a/test/e2e/live_iso_test.go
+++ b/test/e2e/live_iso_test.go
@@ -94,7 +94,7 @@ var _ = Describe("Live-ISO", func() {
 			By("Verifying the node booted from live ISO image")
 			password := e2eConfig.GetVariable("CIRROS_PASSWORD")
 			auth := ssh.Password(password)
-			PerformSSHBootCheck(e2eConfig, "memory", auth, fmt.Sprintf("%s:%s", bmc.IPAddress, bmc.SSHPort))
+			PerformSSHBootCheck(e2eConfig, "memory", auth, fmt.Sprintf("%s:%s", bmc.IpAddress, bmc.SSHPort))
 		} else {
 			capm3_e2e.Logf("WARNING: Skipping SSH check since SSH_CHECK_PROVISIONED != true")
 		}
diff --git a/test/e2e/provisioning_and_annotation_test.go b/test/e2e/provisioning_and_annotation_test.go
index aba7ecf6..dc79a0da 100644
--- a/test/e2e/provisioning_and_annotation_test.go
+++ b/test/e2e/provisioning_and_annotation_test.go
@@ -12,7 +12,7 @@ import (
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
 	corev1 "k8s.io/api/core/v1"
-	k8serrors "k8s.io/apimachinery/pkg/api/errors"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/cluster-api/test/framework"
@@ -128,7 +128,7 @@ var _ = Describe("BMH Provisioning and Annotation Management", func() {
 			Expect(err).NotTo(HaveOccurred(), "unable to parse private key")
 
 			auth := ssh.PublicKeys(signer)
-			PerformSSHBootCheck(e2eConfig, "disk", auth, fmt.Sprintf("%s:%s", bmc.IPAddress, bmc.SSHPort))
+			PerformSSHBootCheck(e2eConfig, "disk", auth, fmt.Sprintf("%s:%s", bmc.IpAddress, bmc.SSHPort))
 		} else {
 			capm3_e2e.Logf("WARNING: Skipping SSH check since SSH_CHECK_PROVISIONED != true")
 		}
@@ -180,7 +180,7 @@ var _ = Describe("BMH Provisioning and Annotation Management", func() {
 				Name:      "bmc-credentials",
 				Namespace: namespace.Name,
 			}, &corev1.Secret{})
-			return k8serrors.IsNotFound(err)
+			return apierrors.IsNotFound(err)
 		}, e2eConfig.GetIntervals(specName, "wait-secret-deletion")...).Should(BeTrue())
 
 		By("Creating a secret with BMH credentials")
diff --git a/test/e2e/upgrade_test.go b/test/e2e/upgrade_test.go
index ef64fb76..9e0354a3 100644
--- a/test/e2e/upgrade_test.go
+++ b/test/e2e/upgrade_test.go
@@ -233,17 +233,15 @@ var _ = Describe("BMO Upgrade", func() {
 		}
 
 		if e2eConfig.GetVariable("UPGRADE_DEPLOY_BMO") != "false" {
-			bmoKustomization := e2eConfig.GetVariable("UPGRADE_BMO_KUSTOMIZATION_FROM")
-			bmoKustomizationName := filepath.Base(bmoKustomization)
-			By(fmt.Sprintf("Installing BMO from %s on the upgrade cluster", bmoKustomization))
+			By("Installing BMO on the upgrade cluster")
 			err := BuildAndApplyKustomize(ctx, &BuildAndApplyKustomizeInput{
-				Kustomization:       bmoKustomization,
+				Kustomization:       e2eConfig.GetVariable("UPGRADE_BMO_KUSTOMIZATION_FROM"),
 				ClusterProxy:        upgradeClusterProxy,
 				WaitForDeployment:   true,
 				WatchDeploymentLogs: true,
 				DeploymentName:      "baremetal-operator-controller-manager",
 				DeploymentNamespace: bmoIronicNamespace,
-				LogPath:             filepath.Join(artifactFolder, "logs", fmt.Sprintf("%s-%s", bmoIronicNamespace, specName), fmt.Sprintf("bmo-%s", bmoKustomizationName)),
+				LogPath:             filepath.Join(artifactFolder, "logs", fmt.Sprintf("%s-%s", bmoIronicNamespace, specName)),
 				WaitIntervals:       e2eConfig.GetIntervals("default", "wait-deployment"),
 			})
 			Expect(err).NotTo(HaveOccurred())
@@ -271,9 +269,7 @@ var _ = Describe("BMO Upgrade", func() {
 				Name:      specName,
 				Namespace: namespace.Name,
 				Annotations: map[string]string{
-					metal3api.InspectAnnotationPrefix: "disabled",
-					// hardwareDetails of release0.4 is compatible to release0.3 and release0.5 as well
-					// This can be changed to the new hardwareDetails once we no longer test release0.4
+					metal3api.InspectAnnotationPrefix:   "disabled",
 					metal3api.HardwareDetailsAnnotation: hardwareDetailsRelease04,
 				},
 			},
@@ -302,17 +298,9 @@ var _ = Describe("BMO Upgrade", func() {
 		bmoDeployName := "baremetal-operator-controller-manager"
 		deploy, err := clientSet.AppsV1().Deployments(bmoIronicNamespace).Get(ctx, bmoDeployName, metav1.GetOptions{})
 		Expect(err).NotTo(HaveOccurred())
-		bmoKustomization := e2eConfig.GetVariable("BMO_KUSTOMIZATION")
-		bmoKustomizationName := filepath.Base(bmoKustomization)
 		err = BuildAndApplyKustomize(ctx, &BuildAndApplyKustomizeInput{
-			Kustomization:       bmoKustomization,
-			ClusterProxy:        upgradeClusterProxy,
-			WaitForDeployment:   false,
-			WatchDeploymentLogs: true,
-			DeploymentName:      "baremetal-operator-controller-manager",
-			DeploymentNamespace: bmoIronicNamespace,
-			LogPath:             filepath.Join(artifactFolder, "logs", fmt.Sprintf("%s-%s", bmoIronicNamespace, specName), fmt.Sprintf("bmo-%s", bmoKustomizationName)),
-			WaitIntervals:       e2eConfig.GetIntervals("default", "wait-deployment"),
+			Kustomization: e2eConfig.GetVariable("BMO_KUSTOMIZATION"),
+			ClusterProxy:  upgradeClusterProxy,
 		})
 		Expect(err).NotTo(HaveOccurred())
 		By("Waiting for BMO update to rollout")
diff --git a/test/go.mod b/test/go.mod
index af4702ea..3f3a8320 100644
--- a/test/go.mod
+++ b/test/go.mod
@@ -1,6 +1,6 @@
 module github.com/metal3-io/baremetal-operator/test
 
-go 1.21
+go 1.20
 
 require (
 	github.com/cert-manager/cert-manager v1.10.0
diff --git a/test/go.sum b/test/go.sum
index a63ba12d..a00e2d94 100644
--- a/test/go.sum
+++ b/test/go.sum
@@ -37,7 +37,6 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
 cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
-github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
@@ -84,9 +83,7 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
 github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0=
-github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4=
 github.com/coredns/corefile-migration v1.0.21 h1:W/DCETrHDiFo0Wj03EyMkaQ9fwsmSgqTCQDHpceaSsE=
-github.com/coredns/corefile-migration v1.0.21/go.mod h1:XnhgULOEouimnzgn0t4WPuFDN2/PJQcTxdWKC5eXNGE=
 github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -120,7 +117,6 @@ github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2Vvl
 github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc=
 github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
 github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
-github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
 github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
@@ -132,7 +128,6 @@ github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV
 github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
 github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo=
-github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA=
 github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
 github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
 github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
@@ -245,7 +240,6 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
 github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
-github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -258,7 +252,6 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
-github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -287,7 +280,6 @@ github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx
 github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
 github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
 github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
-github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -296,7 +288,6 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
 github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
 github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
 github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
-github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@@ -319,7 +310,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
 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/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
 github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -331,14 +321,12 @@ github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwa
 github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
-github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
 github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
 github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
 github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
 github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
-github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
 github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
 github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
@@ -393,11 +381,9 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
 go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY=
 go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
 go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
-go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
 go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
 go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
 go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
-go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -750,7 +736,6 @@ gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
-gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=