Repository: metal3-io/baremetal-operator
Pull request #1456 (2023-11-22 13:56:07)

🌱 Add github action to trigger container images build
This PR adds an action to trigger the bmo and keepalived container builds whenever a PR is merged in this repo.

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 [dtantsur](https://github.com/dtantsur) 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":["dtantsur"]} -->
metal3-io-bot: @mquhuy: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
golint | 3021677d4bd871f28aece933e8738acd0fbfea01 | [link](https://prow.apps.test.metal3.io/view/s3/prow-logs/pr-logs/pull/metal3-io_baremetal-operator/1456/golint/1727331281156444160) | true | `/test golint`

[Full PR test history](https://prow.apps.test.metal3.io/pr-history?org=metal3-io&repo=baremetal-operator&pr=1456). [Your PR dashboard](https://prow.apps.test.metal3.io/pr?query=is:pr+state:open+author:mquhuy).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
elfosardo: /test-ubuntu-integration-main
/test-centos-e2e-integration-main 
elfosardo: /lgtm
metal3-io-bot: New changes are detected. LGTM label has been removed.
mquhuy: /hold

Patch:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index f5d729e5..5abed8a4 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -9,6 +9,8 @@ updates:
       interval: "monthly"
     commit-message:
       prefix: ":seedling:"
+    labels:
+      - "ok-to-test"
     # Go
   - package-ecosystem: "gomod"
     directory: "/"
@@ -22,6 +24,8 @@ updates:
       - dependency-name: "k8s.io/*"
     commit-message:
       prefix: ":seedling:"
+    labels:
+      - "ok-to-test"
   - package-ecosystem: "gomod"
     directory: "/apis"
     schedule:
@@ -34,12 +38,16 @@ updates:
       - dependency-name: "k8s.io/*"
     commit-message:
       prefix: ":seedling:"
+    labels:
+      - "ok-to-test"
   - package-ecosystem: "gomod"
     directory: "/pkg/hardwareutils"
     schedule:
       interval: "weekly"
     commit-message:
       prefix: ":seedling:"
+    labels:
+      - "ok-to-test"
   - package-ecosystem: "gomod"
     directory: "/hack/tools"
     schedule:
@@ -50,3 +58,5 @@ updates:
       - dependency-name: "sigs.k8s.io/controller-tools"
     commit-message:
       prefix: ":seedling:"
+    labels:
+      - "ok-to-test"
diff --git a/.github/workflows/build-images-action.yml b/.github/workflows/build-images-action.yml
new file mode 100644
index 00000000..df137608
--- /dev/null
+++ b/.github/workflows/build-images-action.yml
@@ -0,0 +1,41 @@
+name: build-images-action
+on:
+  push:
+    branches:
+      - 'main'
+      - 'release-*'
+    tags:
+      - 'v*'
+permissions: {}
+jobs:
+  build:
+    name: Build container images
+    runs-on: ubuntu-latest
+    if: github.repository == 'metal3-io/baremetal-operator'
+    permissions:
+      contents: read
+    steps:
+      - name: build bmo image
+        uses: toptal/jenkins-job-trigger-action@137fff703dd260b52b53d3ba1960396415abc568 # 1.0.2
+        with:
+          jenkins_url: "https://jenkins.nordix.org/"
+          jenkins_user: "metal3.bot@gmail.com"
+          jenkins_token: ${{ secrets.JENKINS_TOKEN }}
+          job_name: "metal3_baremetal-operator_container_image_building"
+          job_params: |
+            {
+              "BUILD_CONTAINER_IMAGE_GIT_REFERENCE": "${{ github.ref }}"
+            }
+          job_timeout: "1000"
+      - name: build keepalived image
+        uses: toptal/jenkins-job-trigger-action@137fff703dd260b52b53d3ba1960396415abc568 # 1.0.2
+        with:
+          jenkins_url: "https://jenkins.nordix.org/"
+          jenkins_user: "metal3.bot@gmail.com"
+          jenkins_token: ${{ secrets.JENKINS_TOKEN }}
+          job_name: "metal3_keepalived_container_image_building"
+          job_params: |
+            {
+              "BUILD_CONTAINER_IMAGE_GIT_REFERENCE": "${{ github.ref }}"
+            }
+          job_timeout: "1000"
diff --git a/.github/workflows/kubesec.yml b/.github/workflows/kubesec.yml
index e5213e8d..3fbe245f 100644
--- a/.github/workflows/kubesec.yml
+++ b/.github/workflows/kubesec.yml
@@ -59,6 +59,6 @@ jobs:
 
       - name: Upload Kubesec scan results to GitHub Security tab
         if: ${{ steps.save_result.outputs.result != '[]' }}
-        uses: github/codeql-action/upload-sarif@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
+        uses: github/codeql-action/upload-sarif@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
         with:
           sarif_file: ${{ matrix.value }}.sarif
diff --git a/.github/workflows/pr-verifier.yaml b/.github/workflows/pr-verifier.yaml
index eaa1e9ec..783dce61 100644
--- a/.github/workflows/pr-verifier.yaml
+++ b/.github/workflows/pr-verifier.yaml
@@ -14,6 +14,6 @@ jobs:
     steps:
     - name: Verifier action
       id: verifier
-      uses: kubernetes-sigs/kubebuilder-release-tools@3c3411345eedc489d1022288aa844691e92a9c29 # v0.4.2
+      uses: kubernetes-sigs/kubebuilder-release-tools@e389278c2051863fb39b8de00159c8d7fac760ea # v0.4.1
       with:
         github_token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index c09ed815..3b5f6248 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,13 +44,8 @@ password
 ironic-auth-config
 ironic-inspector-auth-config
 ironic-rpc-auth-config
-ironic-username
-ironic-password
-ironic-inspector-username
-ironic-inspector-password
 HTTP_BASIC_HTPASSWD
 ironic-deployment/overlays/temp
-config/overlays/temp
 
 # Development containers (https://containers.dev/)
 .devcontainer
diff --git a/Dockerfile b/Dockerfile
index c689db57..4882ba86 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
 # Support FROM override
-ARG BUILD_IMAGE=docker.io/golang:1.20.11@sha256:77e4e426190723821471a946a4bdad2d75d9af8209b2841f26744fe766e88444
+ARG BUILD_IMAGE=docker.io/golang:1.20.10@sha256:098d628490c97d4419ed44a23d893f37b764f3bea06e0827183e8af4120e19be
 ARG BASE_IMAGE=gcr.io/distroless/static:nonroot@sha256:9ecc53c269509f63c69a266168e4a687c7eb8c0cfd753bd8bfcaa4f58a90876f
 
 # Build the manager binary
diff --git a/Makefile b/Makefile
index 4c43db2d..d2a204cc 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.20.11
+GO_VERSION ?= 1.20.10
 
 ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
 
@@ -183,8 +183,8 @@ manifests: manifests-generate manifests-kustomize ## Generate manifests e.g. CRD
 
 .PHONY: manifests-generate
 manifests-generate: $(CONTROLLER_GEN)
-	cd apis; $(abspath $<) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:webhook:dir=../config/base/webhook/ output:crd:artifacts:config=../config/base/crds/bases
-	$< rbac:roleName=manager-role paths="./..." output:rbac:artifacts:config=config/base/rbac
+	cd apis; $(abspath $<) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:webhook:dir=../config/webhook/ output:crd:artifacts:config=../config/crd/bases
+	$< rbac:roleName=manager-role paths="./..." output:rbac:artifacts:config=config/rbac
 
 .PHONY: manifests-kustomize
 manifests-kustomize: $(KUSTOMIZE)
@@ -193,7 +193,7 @@ manifests-kustomize: $(KUSTOMIZE)
 .PHONY: set-manifest-image-bmo
 set-manifest-image-bmo: $(KUSTOMIZE) manifests
 	$(info Updating container image for BMO to use ${MANIFEST_IMG}:${MANIFEST_TAG})
-	cd config/base && $(abspath $(KUSTOMIZE)) edit set image quay.io/metal3-io/baremetal-operator=${MANIFEST_IMG}:${MANIFEST_TAG}
+	cd config/default && $(abspath $(KUSTOMIZE)) edit set image quay.io/metal3-io/baremetal-operator=${MANIFEST_IMG}:${MANIFEST_TAG}
 
 .PHONY: set-manifest-image-ironic
 set-manifest-image-ironic: $(KUSTOMIZE) manifests
@@ -333,7 +333,6 @@ go-version: ## Print the go version we use to compile our binaries and images
 .PHONY: clean
 clean: ## Remove all temporary files and folders
 	rm -rf ironic-deployment/overlays/temp
-	rm -rf config/overlays/temp
 
 .PHONY: clean-e2e
 clean-e2e: ## Remove everything related to e2e tests
diff --git a/config/README.md b/config/README.md
deleted file mode 100644
index 275c99a9..00000000
--- a/config/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Kustomizations for Baremetal Operator
-
-This folder contains kustomizations for the Baremetal Operator. They have
-traditionally been used through the [deploy.sh](../tools/deploy.sh) script,
-which takes care of generating the necessary config for basic-auth and TLS.
-However, a more GitOps friendly way would be to create your own static overlay.
-Check the `overlays/e2e` for an example that is used in the e2e tests.
-In the CI system we generate the necessary credentials before starting the test
-in `hack/ci-e2e.sh`, and put them directly in the `e2e` overlays.
-
-**NOTE** that you will need to supply the necessary secrets and config! This can
-be done in many ways, e.g. through the
-[external secrets operator](https://external-secrets.io/latest/) or directly in
-your overlay.
-In the CI system we generate the necessary credentials before starting the test
-in `hack/ci-e2e.sh`, and put them directly in the `e2e` overlays.
-
-- **base** - This is the kustomize base that we start from.
-- **components** - In here you will find re-usable kustomize components for TLS
-  and basic-auth.
-   - **basic-auth** - Enable basic authentication. Note that the basic-auth
-      component is missing the actual credentials. This is on purpose, to make
-      sure that the user is setting the password instead of using sample
-      credentials. The required secrets are:
-      - `ironic-credentials`
-      - `ironic-inspector-credentials`
-   - **tls** - Enable TLS. A CA certificate is needed here to verify the
-      connection to Ironic. If you deploy BMO together with Ironic in a
-      Kubernetes cluster, they can share the secret created for Ironic. The CA
-      should be in a secret:
-      - `ironic-cacert`
-- **default** - A minimal, fully working, BMO kustomization including configmap.
-   Use only for development! There is no TLS or basic-auth.
-- **overlays** - Here you will find ready made overlays that use the above
-   mentioned components. These can be used as examples.
diff --git a/config/base/kustomization.yaml b/config/base/kustomization.yaml
deleted file mode 100644
index 42ad44af..00000000
--- a/config/base/kustomization.yaml
+++ /dev/null
@@ -1,124 +0,0 @@
-# Adds namespace to all resources.
-namespace: baremetal-operator-system
-
-# Value of this field is prepended to the
-# names of all resources, e.g. a deployment named
-# "wordpress" becomes "alices-wordpress".
-# Note that it should also match with the prefix (text before '-') of the namespace
-# field above.
-namePrefix: baremetal-operator-
-
-# Labels to add to all resources and selectors.
-#commonLabels:
-#  someName: someValue
-
-resources:
-- crds
-- rbac
-- manager.yaml
-# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
-# crd/kustomization.yaml
-- webhook
-# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
-- certmanager
-# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
-#- prometheus
-
-generatorOptions:
-  disableNameSuffixHash: true
-
-configMapGenerator:
-- name: manager-config
-  files:
-  - controller_manager_config.yaml
-
-patches:
-# Protect the /metrics endpoint by putting it behind auth.
-# If you want your controller-manager to expose the /metrics
-# endpoint w/o any authn/z, please comment the following line.
-- path: manager_auth_proxy_patch.yaml
-
-# Mount the controller config file for loading manager configurations
-# through a ComponentConfig type
-#- manager_config_patch.yaml
-
-# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
-# crd/kustomization.yaml
-- path: manager_webhook_patch.yaml
-
-# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
-# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
-# 'CERTMANAGER' needs to be enabled to use ca injection
-- path: webhookcainjection_patch.yaml
-
-replacements:
-- source:
-    kind: Certificate
-    group: cert-manager.io
-    version: v1
-    name: serving-cert # this name should match the one in certificate.yaml
-    fieldpath: metadata.namespace
-  targets:
-  - select:
-      kind: ValidatingWebhookConfiguration
-    fieldPaths:
-      - metadata.annotations.[cert-manager.io/inject-ca-from]
-    options:
-      delimiter: '/'
-      index: 0
-  - select:
-      kind: CustomResourceDefinition
-      name: baremetalhosts.metal3.io
-    fieldPaths:
-      - metadata.annotations.[cert-manager.io/inject-ca-from]
-    options:
-      delimiter: '/'
-      index: 0
-- source:
-    kind: Certificate
-    group: cert-manager.io
-    version: v1
-    name: serving-cert # this name should match the one in certificate.yaml
-    fieldpath: metadata.name
-  targets:
-  - select:
-      kind: ValidatingWebhookConfiguration
-    fieldPaths:
-      - metadata.annotations.[cert-manager.io/inject-ca-from]
-    options:
-      delimiter: '/'
-      index: 1
-  - select:
-      kind: CustomResourceDefinition
-      name: baremetalhosts.metal3.io
-    fieldPaths:
-      - metadata.annotations.[cert-manager.io/inject-ca-from]
-    options:
-      delimiter: '/'
-      index: 1
-- source:
-    kind: Service
-    version: v1
-    name: webhook-service
-    fieldpath: metadata.namespace
-  targets:
-  - select:
-      kind: Certificate
-    fieldPaths:
-    - spec.dnsNames.*
-    options:
-      delimiter: '.'
-      index: 1
-- source:
-    kind: Service
-    version: v1
-    name: webhook-service
-    fieldpath: metadata.name
-  targets:
-  - select:
-      kind: Certificate
-    fieldPaths:
-    - spec.dnsNames.*
-    options:
-      delimiter: '.'
-      index: 0
diff --git a/config/components/basic-auth/credentials_patch.yaml b/config/basic-auth/default/credentials_patch.yaml
similarity index 100%
rename from config/components/basic-auth/credentials_patch.yaml
rename to config/basic-auth/default/credentials_patch.yaml
diff --git a/config/basic-auth/default/kustomization.yaml b/config/basic-auth/default/kustomization.yaml
new file mode 100644
index 00000000..1348a9e5
--- /dev/null
+++ b/config/basic-auth/default/kustomization.yaml
@@ -0,0 +1,19 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+namespace: baremetal-operator-system
+resources:
+- ../../default
+- ../../namespace
+
+secretGenerator:
+  - name: ironic-credentials
+    files:
+    - username=ironic-username
+    - password=ironic-password
+  - name: ironic-inspector-credentials
+    files:
+    - username=ironic-inspector-username
+    - password=ironic-inspector-password
+
+patches:
+- path: credentials_patch.yaml
diff --git a/config/basic-auth/tls/credentials_patch.yaml b/config/basic-auth/tls/credentials_patch.yaml
new file mode 100644
index 00000000..c3a600f7
--- /dev/null
+++ b/config/basic-auth/tls/credentials_patch.yaml
@@ -0,0 +1,24 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: controller-manager
+  namespace: system
+spec:
+  template:
+    spec:
+      containers:
+      - name: manager
+        volumeMounts:
+        - name: ironic-credentials
+          mountPath: "/opt/metal3/auth/ironic"
+          readOnly: true
+        - name: ironic-inspector-credentials
+          mountPath: "/opt/metal3/auth/ironic-inspector"
+          readOnly: true
+      volumes:
+      - name: ironic-credentials
+        secret:
+          secretName: ironic-credentials
+      - name: ironic-inspector-credentials
+        secret:
+          secretName: ironic-inspector-credentials
diff --git a/config/basic-auth/tls/kustomization.yaml b/config/basic-auth/tls/kustomization.yaml
new file mode 100644
index 00000000..cbcbbbfd
--- /dev/null
+++ b/config/basic-auth/tls/kustomization.yaml
@@ -0,0 +1,18 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+namespace: baremetal-operator-system
+resources:
+- ../../tls
+
+secretGenerator:
+  - name: ironic-credentials
+    files:
+    - username=ironic-username
+    - password=ironic-password
+  - name: ironic-inspector-credentials
+    files:
+    - username=ironic-inspector-username
+    - password=ironic-inspector-password
+
+patches:
+- path: credentials_patch.yaml
diff --git a/config/base/certmanager/certificate.yaml b/config/certmanager/certificate.yaml
similarity index 100%
rename from config/base/certmanager/certificate.yaml
rename to config/certmanager/certificate.yaml
diff --git a/config/base/certmanager/kustomization.yaml b/config/certmanager/kustomization.yaml
similarity index 100%
rename from config/base/certmanager/kustomization.yaml
rename to config/certmanager/kustomization.yaml
diff --git a/config/base/certmanager/kustomizeconfig.yaml b/config/certmanager/kustomizeconfig.yaml
similarity index 100%
rename from config/base/certmanager/kustomizeconfig.yaml
rename to config/certmanager/kustomizeconfig.yaml
diff --git a/config/components/basic-auth/kustomization.yaml b/config/components/basic-auth/kustomization.yaml
deleted file mode 100644
index 44e9f0c4..00000000
--- a/config/components/basic-auth/kustomization.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-apiVersion: kustomize.config.k8s.io/v1alpha1
-kind: Component
-
-# NOTE: This component requires secrets with the basic auth credentials!
-# How you create them is up to you.
-# The required secrets are:
-# - ironic-credentials
-# - ironic-inspector-credentials
-#
-# Both should contain 2 fields: username and password.
-# Example:
-#
-# apiVersion: v1
-# kind: Secret
-# metadata:
-#   name: ironic-credentials
-# data:
-#   password: <base64-encoded-password>
-#   username: <base64-encoded-username>
-
-patches:
-- path: credentials_patch.yaml
diff --git a/config/components/tls/kustomization.yaml b/config/components/tls/kustomization.yaml
deleted file mode 100644
index 3854f302..00000000
--- a/config/components/tls/kustomization.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-apiVersion: kustomize.config.k8s.io/v1alpha1
-kind: Component
-
-patches:
-- path: tls_ca_patch.yaml
-  target:
-    kind: Deployment
-    name: controller-manager
diff --git a/config/base/crds/bases/metal3.io_baremetalhosts.yaml b/config/crd/bases/metal3.io_baremetalhosts.yaml
similarity index 100%
rename from config/base/crds/bases/metal3.io_baremetalhosts.yaml
rename to config/crd/bases/metal3.io_baremetalhosts.yaml
diff --git a/config/base/crds/bases/metal3.io_bmceventsubscriptions.yaml b/config/crd/bases/metal3.io_bmceventsubscriptions.yaml
similarity index 100%
rename from config/base/crds/bases/metal3.io_bmceventsubscriptions.yaml
rename to config/crd/bases/metal3.io_bmceventsubscriptions.yaml
diff --git a/config/base/crds/bases/metal3.io_firmwareschemas.yaml b/config/crd/bases/metal3.io_firmwareschemas.yaml
similarity index 100%
rename from config/base/crds/bases/metal3.io_firmwareschemas.yaml
rename to config/crd/bases/metal3.io_firmwareschemas.yaml
diff --git a/config/base/crds/bases/metal3.io_hardwaredata.yaml b/config/crd/bases/metal3.io_hardwaredata.yaml
similarity index 100%
rename from config/base/crds/bases/metal3.io_hardwaredata.yaml
rename to config/crd/bases/metal3.io_hardwaredata.yaml
diff --git a/config/base/crds/bases/metal3.io_hostfirmwaresettings.yaml b/config/crd/bases/metal3.io_hostfirmwaresettings.yaml
similarity index 100%
rename from config/base/crds/bases/metal3.io_hostfirmwaresettings.yaml
rename to config/crd/bases/metal3.io_hostfirmwaresettings.yaml
diff --git a/config/base/crds/bases/metal3.io_preprovisioningimages.yaml b/config/crd/bases/metal3.io_preprovisioningimages.yaml
similarity index 100%
rename from config/base/crds/bases/metal3.io_preprovisioningimages.yaml
rename to config/crd/bases/metal3.io_preprovisioningimages.yaml
diff --git a/config/base/crds/kustomization.yaml b/config/crd/kustomization.yaml
similarity index 100%
rename from config/base/crds/kustomization.yaml
rename to config/crd/kustomization.yaml
diff --git a/config/base/crds/kustomizeconfig.yaml b/config/crd/kustomizeconfig.yaml
similarity index 100%
rename from config/base/crds/kustomizeconfig.yaml
rename to config/crd/kustomizeconfig.yaml
diff --git a/config/base/crds/patches/cainjection_in_baremetalhosts.yaml b/config/crd/patches/cainjection_in_baremetalhosts.yaml
similarity index 100%
rename from config/base/crds/patches/cainjection_in_baremetalhosts.yaml
rename to config/crd/patches/cainjection_in_baremetalhosts.yaml
diff --git a/config/base/crds/patches/cainjection_in_bmceventsubscriptions.yaml b/config/crd/patches/cainjection_in_bmceventsubscriptions.yaml
similarity index 100%
rename from config/base/crds/patches/cainjection_in_bmceventsubscriptions.yaml
rename to config/crd/patches/cainjection_in_bmceventsubscriptions.yaml
diff --git a/config/base/crds/patches/cainjection_in_firmwareschemas.yaml b/config/crd/patches/cainjection_in_firmwareschemas.yaml
similarity index 100%
rename from config/base/crds/patches/cainjection_in_firmwareschemas.yaml
rename to config/crd/patches/cainjection_in_firmwareschemas.yaml
diff --git a/config/base/crds/patches/cainjection_in_hardwaredata.yaml b/config/crd/patches/cainjection_in_hardwaredata.yaml
similarity index 100%
rename from config/base/crds/patches/cainjection_in_hardwaredata.yaml
rename to config/crd/patches/cainjection_in_hardwaredata.yaml
diff --git a/config/base/crds/patches/cainjection_in_hostfirmwaresettings.yaml b/config/crd/patches/cainjection_in_hostfirmwaresettings.yaml
similarity index 100%
rename from config/base/crds/patches/cainjection_in_hostfirmwaresettings.yaml
rename to config/crd/patches/cainjection_in_hostfirmwaresettings.yaml
diff --git a/config/base/crds/patches/cainjection_in_preprovisioningimages.yaml b/config/crd/patches/cainjection_in_preprovisioningimages.yaml
similarity index 100%
rename from config/base/crds/patches/cainjection_in_preprovisioningimages.yaml
rename to config/crd/patches/cainjection_in_preprovisioningimages.yaml
diff --git a/config/base/crds/patches/webhook_in_baremetalhosts.yaml b/config/crd/patches/webhook_in_baremetalhosts.yaml
similarity index 100%
rename from config/base/crds/patches/webhook_in_baremetalhosts.yaml
rename to config/crd/patches/webhook_in_baremetalhosts.yaml
diff --git a/config/base/crds/patches/webhook_in_bmceventsubscriptions.yaml b/config/crd/patches/webhook_in_bmceventsubscriptions.yaml
similarity index 100%
rename from config/base/crds/patches/webhook_in_bmceventsubscriptions.yaml
rename to config/crd/patches/webhook_in_bmceventsubscriptions.yaml
diff --git a/config/base/crds/patches/webhook_in_firmwareschemas.yaml b/config/crd/patches/webhook_in_firmwareschemas.yaml
similarity index 100%
rename from config/base/crds/patches/webhook_in_firmwareschemas.yaml
rename to config/crd/patches/webhook_in_firmwareschemas.yaml
diff --git a/config/base/crds/patches/webhook_in_hardwaredata.yaml b/config/crd/patches/webhook_in_hardwaredata.yaml
similarity index 100%
rename from config/base/crds/patches/webhook_in_hardwaredata.yaml
rename to config/crd/patches/webhook_in_hardwaredata.yaml
diff --git a/config/base/crds/patches/webhook_in_hostfirmwaresettings.yaml b/config/crd/patches/webhook_in_hostfirmwaresettings.yaml
similarity index 100%
rename from config/base/crds/patches/webhook_in_hostfirmwaresettings.yaml
rename to config/crd/patches/webhook_in_hostfirmwaresettings.yaml
diff --git a/config/base/crds/patches/webhook_in_preprovisioningimages.yaml b/config/crd/patches/webhook_in_preprovisioningimages.yaml
similarity index 100%
rename from config/base/crds/patches/webhook_in_preprovisioningimages.yaml
rename to config/crd/patches/webhook_in_preprovisioningimages.yaml
diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml
index be091dcf..f6ea3bfe 100644
--- a/config/default/kustomization.yaml
+++ b/config/default/kustomization.yaml
@@ -1,14 +1,126 @@
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
+# Adds namespace to all resources.
 namespace: baremetal-operator-system
+
+# Value of this field is prepended to the
+# names of all resources, e.g. a deployment named
+# "wordpress" becomes "alices-wordpress".
+# Note that it should also match with the prefix (text before '-') of the namespace
+# field above.
+namePrefix: baremetal-operator-
+
+# Labels to add to all resources and selectors.
+#commonLabels:
+#  someName: someValue
+
 resources:
-- ../base
+- ../crd
+- ../rbac
+- ../manager
+# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
+# crd/kustomization.yaml
+- ../webhook
+# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
+- ../certmanager
+# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
+#- ../prometheus
+
+patches:
+# Protect the /metrics endpoint by putting it behind auth.
+# If you want your controller-manager to expose the /metrics
+# endpoint w/o any authn/z, please comment the following line.
+- path: manager_auth_proxy_patch.yaml
+
+# Mount the controller config file for loading manager configurations
+# through a ComponentConfig type
+#- manager_config_patch.yaml
+
+# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
+# crd/kustomization.yaml
+- path: manager_webhook_patch.yaml
+
+# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
+# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
+# 'CERTMANAGER' needs to be enabled to use ca injection
+- path: webhookcainjection_patch.yaml
+
+replacements:
+- source:
+    kind: Certificate
+    group: cert-manager.io
+    version: v1
+    name: serving-cert # this name should match the one in certificate.yaml
+    fieldpath: metadata.namespace
+  targets:
+  - select:
+      kind: ValidatingWebhookConfiguration
+    fieldPaths:
+      - metadata.annotations.[cert-manager.io/inject-ca-from]
+    options:
+      delimiter: '/'
+      index: 0
+  - select:
+      kind: CustomResourceDefinition
+      name: baremetalhosts.metal3.io
+    fieldPaths:
+      - metadata.annotations.[cert-manager.io/inject-ca-from]
+    options:
+      delimiter: '/'
+      index: 0
+- source:
+    kind: Certificate
+    group: cert-manager.io
+    version: v1
+    name: serving-cert # this name should match the one in certificate.yaml
+    fieldpath: metadata.name
+  targets:
+  - select:
+      kind: ValidatingWebhookConfiguration
+    fieldPaths:
+      - metadata.annotations.[cert-manager.io/inject-ca-from]
+    options:
+      delimiter: '/'
+      index: 1
+  - select:
+      kind: CustomResourceDefinition
+      name: baremetalhosts.metal3.io
+    fieldPaths:
+      - metadata.annotations.[cert-manager.io/inject-ca-from]
+    options:
+      delimiter: '/'
+      index: 1
+- source:
+    kind: Service
+    version: v1
+    name: webhook-service
+    fieldpath: metadata.namespace
+  targets:
+  - select:
+      kind: Certificate
+    fieldPaths:
+    - spec.dnsNames.*
+    options:
+      delimiter: '.'
+      index: 1
+- source:
+    kind: Service
+    version: v1
+    name: webhook-service
+    fieldpath: metadata.name
+  targets:
+  - select:
+      kind: Certificate
+    fieldPaths:
+    - spec.dnsNames.*
+    options:
+      delimiter: '.'
+      index: 0
 
+# Add ironic configmap-generator
 generatorOptions:
  disableNameSuffixHash: true
 
 configMapGenerator:
-- name: ironic
-  behavior: create
+- behavior: create
   envs:
   - ironic.env
+  name: ironic
diff --git a/config/base/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml
similarity index 100%
rename from config/base/manager_auth_proxy_patch.yaml
rename to config/default/manager_auth_proxy_patch.yaml
diff --git a/config/base/manager_config_patch.yaml b/config/default/manager_config_patch.yaml
similarity index 100%
rename from config/base/manager_config_patch.yaml
rename to config/default/manager_config_patch.yaml
diff --git a/config/base/manager_webhook_patch.yaml b/config/default/manager_webhook_patch.yaml
similarity index 100%
rename from config/base/manager_webhook_patch.yaml
rename to config/default/manager_webhook_patch.yaml
diff --git a/config/base/webhookcainjection_patch.yaml b/config/default/webhookcainjection_patch.yaml
similarity index 100%
rename from config/base/webhookcainjection_patch.yaml
rename to config/default/webhookcainjection_patch.yaml
diff --git a/config/base/controller_manager_config.yaml b/config/manager/controller_manager_config.yaml
similarity index 100%
rename from config/base/controller_manager_config.yaml
rename to config/manager/controller_manager_config.yaml
diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml
new file mode 100644
index 00000000..2bcd3eea
--- /dev/null
+++ b/config/manager/kustomization.yaml
@@ -0,0 +1,10 @@
+resources:
+- manager.yaml
+
+generatorOptions:
+  disableNameSuffixHash: true
+
+configMapGenerator:
+- name: manager-config
+  files:
+  - controller_manager_config.yaml
diff --git a/config/base/manager.yaml b/config/manager/manager.yaml
similarity index 100%
rename from config/base/manager.yaml
rename to config/manager/manager.yaml
diff --git a/config/overlays/basic-auth_tls/kustomization.yaml b/config/overlays/basic-auth_tls/kustomization.yaml
deleted file mode 100644
index 490f7c0b..00000000
--- a/config/overlays/basic-auth_tls/kustomization.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-
-resources:
-  - ../../namespace
-  - ../../base
-
-components:
-  - ../../components/basic-auth
-  - ../../components/tls
-# Example for how to generate the necessary secrets:
-# 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/base/prometheus/kustomization.yaml b/config/prometheus/kustomization.yaml
similarity index 100%
rename from config/base/prometheus/kustomization.yaml
rename to config/prometheus/kustomization.yaml
diff --git a/config/base/prometheus/monitor.yaml b/config/prometheus/monitor.yaml
similarity index 100%
rename from config/base/prometheus/monitor.yaml
rename to config/prometheus/monitor.yaml
diff --git a/config/base/rbac/auth_proxy_client_clusterrole.yaml b/config/rbac/auth_proxy_client_clusterrole.yaml
similarity index 100%
rename from config/base/rbac/auth_proxy_client_clusterrole.yaml
rename to config/rbac/auth_proxy_client_clusterrole.yaml
diff --git a/config/base/rbac/auth_proxy_role.yaml b/config/rbac/auth_proxy_role.yaml
similarity index 100%
rename from config/base/rbac/auth_proxy_role.yaml
rename to config/rbac/auth_proxy_role.yaml
diff --git a/config/base/rbac/auth_proxy_role_binding.yaml b/config/rbac/auth_proxy_role_binding.yaml
similarity index 100%
rename from config/base/rbac/auth_proxy_role_binding.yaml
rename to config/rbac/auth_proxy_role_binding.yaml
diff --git a/config/base/rbac/auth_proxy_service.yaml b/config/rbac/auth_proxy_service.yaml
similarity index 100%
rename from config/base/rbac/auth_proxy_service.yaml
rename to config/rbac/auth_proxy_service.yaml
diff --git a/config/base/rbac/baremetalhost_editor_role.yaml b/config/rbac/baremetalhost_editor_role.yaml
similarity index 100%
rename from config/base/rbac/baremetalhost_editor_role.yaml
rename to config/rbac/baremetalhost_editor_role.yaml
diff --git a/config/base/rbac/baremetalhost_viewer_role.yaml b/config/rbac/baremetalhost_viewer_role.yaml
similarity index 100%
rename from config/base/rbac/baremetalhost_viewer_role.yaml
rename to config/rbac/baremetalhost_viewer_role.yaml
diff --git a/config/base/rbac/bmceventsubscription_editor_role.yaml b/config/rbac/bmceventsubscription_editor_role.yaml
similarity index 100%
rename from config/base/rbac/bmceventsubscription_editor_role.yaml
rename to config/rbac/bmceventsubscription_editor_role.yaml
diff --git a/config/base/rbac/bmceventsubscription_viewer_role.yaml b/config/rbac/bmceventsubscription_viewer_role.yaml
similarity index 100%
rename from config/base/rbac/bmceventsubscription_viewer_role.yaml
rename to config/rbac/bmceventsubscription_viewer_role.yaml
diff --git a/config/base/rbac/firmwareschema_editor_role.yaml b/config/rbac/firmwareschema_editor_role.yaml
similarity index 100%
rename from config/base/rbac/firmwareschema_editor_role.yaml
rename to config/rbac/firmwareschema_editor_role.yaml
diff --git a/config/base/rbac/firmwareschema_viewer_role.yaml b/config/rbac/firmwareschema_viewer_role.yaml
similarity index 100%
rename from config/base/rbac/firmwareschema_viewer_role.yaml
rename to config/rbac/firmwareschema_viewer_role.yaml
diff --git a/config/base/rbac/hardwaredata_editor_role.yaml b/config/rbac/hardwaredata_editor_role.yaml
similarity index 100%
rename from config/base/rbac/hardwaredata_editor_role.yaml
rename to config/rbac/hardwaredata_editor_role.yaml
diff --git a/config/base/rbac/hardwaredata_viewer_role.yaml b/config/rbac/hardwaredata_viewer_role.yaml
similarity index 100%
rename from config/base/rbac/hardwaredata_viewer_role.yaml
rename to config/rbac/hardwaredata_viewer_role.yaml
diff --git a/config/base/rbac/hostfirmwaresettings_editor_role.yaml b/config/rbac/hostfirmwaresettings_editor_role.yaml
similarity index 100%
rename from config/base/rbac/hostfirmwaresettings_editor_role.yaml
rename to config/rbac/hostfirmwaresettings_editor_role.yaml
diff --git a/config/base/rbac/hostfirmwaresettings_viewer_role.yaml b/config/rbac/hostfirmwaresettings_viewer_role.yaml
similarity index 100%
rename from config/base/rbac/hostfirmwaresettings_viewer_role.yaml
rename to config/rbac/hostfirmwaresettings_viewer_role.yaml
diff --git a/config/base/rbac/kustomization.yaml b/config/rbac/kustomization.yaml
similarity index 100%
rename from config/base/rbac/kustomization.yaml
rename to config/rbac/kustomization.yaml
diff --git a/config/base/rbac/leader_election_role.yaml b/config/rbac/leader_election_role.yaml
similarity index 100%
rename from config/base/rbac/leader_election_role.yaml
rename to config/rbac/leader_election_role.yaml
diff --git a/config/base/rbac/leader_election_role_binding.yaml b/config/rbac/leader_election_role_binding.yaml
similarity index 100%
rename from config/base/rbac/leader_election_role_binding.yaml
rename to config/rbac/leader_election_role_binding.yaml
diff --git a/config/base/rbac/preprovisioningimage_editor_role.yaml b/config/rbac/preprovisioningimage_editor_role.yaml
similarity index 100%
rename from config/base/rbac/preprovisioningimage_editor_role.yaml
rename to config/rbac/preprovisioningimage_editor_role.yaml
diff --git a/config/base/rbac/preprovisioningimage_viewer_role.yaml b/config/rbac/preprovisioningimage_viewer_role.yaml
similarity index 100%
rename from config/base/rbac/preprovisioningimage_viewer_role.yaml
rename to config/rbac/preprovisioningimage_viewer_role.yaml
diff --git a/config/base/rbac/role.yaml b/config/rbac/role.yaml
similarity index 100%
rename from config/base/rbac/role.yaml
rename to config/rbac/role.yaml
diff --git a/config/base/rbac/role_binding.yaml b/config/rbac/role_binding.yaml
similarity index 100%
rename from config/base/rbac/role_binding.yaml
rename to config/rbac/role_binding.yaml
diff --git a/config/base/rbac/service_account.yaml b/config/rbac/service_account.yaml
similarity index 100%
rename from config/base/rbac/service_account.yaml
rename to config/rbac/service_account.yaml
diff --git a/config/render/capm3.yaml b/config/render/capm3.yaml
index ba6d83f1..96590dd6 100644
--- a/config/render/capm3.yaml
+++ b/config/render/capm3.yaml
@@ -2132,6 +2132,21 @@ subjects:
   namespace: baremetal-operator-system
 ---
 apiVersion: v1
+data:
+  CACHEURL: http://172.22.0.1/images
+  DEPLOY_KERNEL_URL: http://172.22.0.2:6180/images/ironic-python-agent.kernel
+  DEPLOY_RAMDISK_URL: http://172.22.0.2:6180/images/ironic-python-agent.initramfs
+  DHCP_RANGE: 172.22.0.10,172.22.0.100
+  HTTP_PORT: "6180"
+  IRONIC_ENDPOINT: http://172.22.0.2:6385/v1/
+  IRONIC_FAST_TRACK: "true"
+  PROVISIONING_INTERFACE: eth2
+kind: ConfigMap
+metadata:
+  name: baremetal-operator-ironic
+  namespace: baremetal-operator-system
+---
+apiVersion: v1
 data:
   controller_manager_config.yaml: |
     apiVersion: controller-runtime.sigs.k8s.io/v1alpha1
@@ -2151,21 +2166,6 @@ metadata:
   namespace: baremetal-operator-system
 ---
 apiVersion: v1
-data:
-  CACHEURL: http://172.22.0.1/images
-  DEPLOY_KERNEL_URL: http://172.22.0.2:6180/images/ironic-python-agent.kernel
-  DEPLOY_RAMDISK_URL: http://172.22.0.2:6180/images/ironic-python-agent.initramfs
-  DHCP_RANGE: 172.22.0.10,172.22.0.100
-  HTTP_PORT: "6180"
-  IRONIC_ENDPOINT: http://172.22.0.2:6385/v1/
-  IRONIC_FAST_TRACK: "true"
-  PROVISIONING_INTERFACE: eth2
-kind: ConfigMap
-metadata:
-  name: ironic
-  namespace: baremetal-operator-system
----
-apiVersion: v1
 kind: Service
 metadata:
   labels:
@@ -2230,7 +2230,7 @@ spec:
               fieldPath: metadata.namespace
         envFrom:
         - configMapRef:
-            name: ironic
+            name: baremetal-operator-ironic
         image: quay.io/metal3-io/baremetal-operator
         imagePullPolicy: Always
         livenessProbe:
diff --git a/config/tls/kustomization.yaml b/config/tls/kustomization.yaml
new file mode 100644
index 00000000..b9a5f75e
--- /dev/null
+++ b/config/tls/kustomization.yaml
@@ -0,0 +1,9 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+namespace: baremetal-operator-system
+resources:
+- ../default
+- ../namespace
+
+patches:
+- path: tls_ca_patch.yaml
diff --git a/config/components/tls/tls_ca_patch.yaml b/config/tls/tls_ca_patch.yaml
similarity index 85%
rename from config/components/tls/tls_ca_patch.yaml
rename to config/tls/tls_ca_patch.yaml
index ae8fc021..b28d9d43 100644
--- a/config/components/tls/tls_ca_patch.yaml
+++ b/config/tls/tls_ca_patch.yaml
@@ -2,6 +2,7 @@ apiVersion: apps/v1
 kind: Deployment
 metadata:
   name: controller-manager
+  namespace: system
 spec:
   template:
     spec:
@@ -14,4 +15,4 @@ spec:
       volumes:
       - name: cacert
         secret:
-          secretName: ironic-cacert
+          secretName: ironic-cacert
\ No newline at end of file
diff --git a/config/base/webhook/kustomization.yaml b/config/webhook/kustomization.yaml
similarity index 100%
rename from config/base/webhook/kustomization.yaml
rename to config/webhook/kustomization.yaml
diff --git a/config/base/webhook/kustomizeconfig.yaml b/config/webhook/kustomizeconfig.yaml
similarity index 100%
rename from config/base/webhook/kustomizeconfig.yaml
rename to config/webhook/kustomizeconfig.yaml
diff --git a/config/base/webhook/manifests.yaml b/config/webhook/manifests.yaml
similarity index 100%
rename from config/base/webhook/manifests.yaml
rename to config/webhook/manifests.yaml
diff --git a/config/base/webhook/service_patch.yaml b/config/webhook/service_patch.yaml
similarity index 100%
rename from config/base/webhook/service_patch.yaml
rename to config/webhook/service_patch.yaml
diff --git a/go.mod b/go.mod
index 104858c6..69f0b396 100644
--- a/go.mod
+++ b/go.mod
@@ -14,7 +14,6 @@ require (
 	github.com/stretchr/testify v1.8.4
 	go.etcd.io/etcd/client/pkg/v3 v3.5.10
 	go.uber.org/zap v1.26.0
-	golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
 	k8s.io/api v0.27.7
 	k8s.io/apimachinery v0.27.7
 	k8s.io/client-go v0.27.7
@@ -60,6 +59,7 @@ require (
 	github.com/spf13/cobra v1.6.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	go.uber.org/multierr v1.10.0 // indirect
+	golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
 	golang.org/x/net v0.17.0 // indirect
 	golang.org/x/oauth2 v0.8.0 // indirect
 	golang.org/x/sys v0.14.0 // indirect
diff --git a/hack/gosec.sh b/hack/gosec.sh
index 0b809822..28e72a94 100755
--- a/hack/gosec.sh
+++ b/hack/gosec.sh
@@ -19,6 +19,6 @@ else
     --volume "${PWD}:/go/src/github.com/metal3-io/baremetal-operator:ro,z" \
     --entrypoint sh \
     --workdir /go/src/github.com/metal3-io/baremetal-operator \
-    docker.io/securego/gosec:2.18.2@sha256:2f9daee1739765788945b79de7f46229f33fda5ed35127393d8a1e459f3a7577 \
-    /go/src/github.com/metal3-io/baremetal-operator/hack/gosec.sh "$@"
-fi
+    docker.io/securego/gosec:2.14.0@sha256:73858f8b1b9b7372917677151ec6deeceeaa40c5b02753080bd647dede14e213 \
+    /go/src/github.com/metal3-io/baremetal-operator/hack/gosec.sh "${@}"
+fi;
diff --git a/hack/markdownlint.sh b/hack/markdownlint.sh
index ab9b9105..d556b25c 100755
--- a/hack/markdownlint.sh
+++ b/hack/markdownlint.sh
@@ -1,12 +1,5 @@
 #!/bin/bash
 
-# TODO:
-# Fix these two failures in future commit, and remove the ignore rules
-#
-# Further documentation is available for these failures:
-# - MD029: https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md#md029---ordered-list-item-prefix
-# - MD013: https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md#md013---line-length
-
 set -eux
 
 IS_CONTAINER=${IS_CONTAINER:-false}
@@ -18,7 +11,7 @@ if [ "${IS_CONTAINER}" != "false" ]; then
        \( -path ./vendor -o -path ./.github \) \
       -prune -o -name '*.md' -exec \
       mdl --style all --warnings \
-      --rules "~MD013,~MD029" \
+      --rules "MD001,MD002,MD003,MD004,MD005,MD006,MD007,MD009,MD010,MD011,MD012,MD014,MD018,MD019,MD020,MD021,MD022,MD023,MD024,MD025,MD026,MD027,MD028,MD030,MD031,MD032,MD033,MD034,MD035,MD036,MD037,MD038,MD039,MD040,MD041" \
       {} \+
 else
   "${CONTAINER_RUNTIME}" run --rm \
@@ -26,6 +19,45 @@ else
     --volume "${PWD}:/workdir:ro,z" \
     --entrypoint sh \
     --workdir /workdir \
-    docker.io/pipelinecomponents/markdownlint:0.13.0@sha256:9c0cdfb64fd3f1d3bdc5181629b39c2e43b6a52fc9fdc146611e1860845bbae0 \
+    docker.io/pipelinecomponents/markdownlint:0.12.0@sha256:0b8f9fcf0410257b2f3548f67ffe25934cfc9877a618b9f85afcf345a25804a2 \
     /workdir/hack/markdownlint.sh "$@"
-fi
+fi;
+
+# $ mdl --style all -l
+# MD001 - Header levels should only increment by one level at a time
+# MD002 - First header should be a top level header
+# MD003 - Header style
+# MD004 - Unordered list style
+# MD005 - Inconsistent indentation for list items at the same level
+# MD006 - Consider starting bulleted lists at the beginning of the line
+# MD007 - Unordered list indentation
+# MD009 - Trailing spaces
+# MD010 - Hard tabs
+# MD011 - Reversed link syntax
+# MD012 - Multiple consecutive blank lines
+# MD014 - Dollar signs used before commands without showing output
+# MD018 - No space after hash on atx style header
+# MD019 - Multiple spaces after hash on atx style header
+# MD020 - No space inside hashes on closed atx style header
+# MD021 - Multiple spaces inside hashes on closed atx style header
+# MD022 - Headers should be surrounded by blank lines
+# MD023 - Headers must start at the beginning of the line
+# MD024 - Multiple headers with the same content
+# MD025 - Multiple top level headers in the same document
+# MD026 - Trailing punctuation in header
+# MD027 - Multiple spaces after blockquote symbol
+# MD028 - Blank line inside blockquote
+# MD029 - Ordered list item prefix - DISABLED
+# MD030 - Spaces after list markers
+# MD031 - Fenced code blocks should be surrounded by blank lines
+# MD032 - Lists should be surrounded by blank lines
+# MD033 - Inline HTML
+# MD034 - Bare URL used
+# MD035 - Horizontal rule style
+# MD036 - Emphasis used instead of a header
+# MD037 - Spaces inside emphasis markers
+# MD038 - Spaces inside code span elements
+# MD039 - Spaces inside link text
+# MD040 - Fenced code blocks should have a language specified
+# MD041 - First line in file should be a top level header
+# MD046 - Code block style - DISABLED
diff --git a/hack/verify-release.sh b/hack/verify-release.sh
index 79f1351e..44846c5a 100755
--- a/hack/verify-release.sh
+++ b/hack/verify-release.sh
@@ -59,8 +59,6 @@ REGISTRY="quay.io"
 
 # if the given tag doesn't exist, we run only pre-tag checks
 TAG_EXISTS=""
-# we skip some checks if we cannot download release information
-RELEASE_EXISTS=""
 
 
 #
@@ -269,29 +267,16 @@ download_release_information()
 {
     # download release information json, requires GITHUB_TOKEN
     echo "Downloading release information ..."
-    local release_id
 
     if ! curl -SsL --fail \
             -H "Accept: application/vnd.github+json" \
             -H "Authorization: Bearer ${GITHUB_TOKEN}" \
             -H "X-GitHub-Api-Version: 2022-11-28" \
             -o "${RELEASE_JSON}" \
-            "https://api.github.com/repos/${PROJECT}/releases" >/dev/null; then
+            "https://api.github.com/repos/${PROJECT}/releases/tags/v${VERSION}" >/dev/null; then
         echo "ERROR: could not download release information, check token and permissions"
         exit 1
     fi
-    release_id=$(jq '.[] | select(.name == "v'"${VERSION}"'") | .id' "${RELEASE_JSON}")
-
-    if [[ -z "${release_id}" ]] || ! curl -SsL --fail \
-            -H "Accept: application/vnd.github+json" \
-            -H "Authorization: Bearer ${GITHUB_TOKEN}" \
-            -H "X-GitHub-Api-Version: 2022-11-28" \
-            -o "${RELEASE_JSON}" \
-            "https://api.github.com/repos/${PROJECT}/releases/${release_id}" >/dev/null; then
-        echo "WARNING: could not download release information for tag v${VERSION} (id '${release_id}')"
-        echo "WARNING: will skip all release note checks"
-    fi
-    RELEASE_EXISTS=true
 
     echo -e "Done\n"
 }
@@ -556,7 +541,7 @@ verify_vulnerabilities()
     # run osv-scanner to verify if we have open vulnerabilities in deps
     echo "Verifying vulnerabilities ..."
 
-    "${OSVSCANNER_CMD[@]}" -r . > "${SCAN_LOG}" || true
+    "${OSVSCANNER_CMD[@]}" -r . > "${SCAN_LOG}"
     if ! grep -q "No vulnerabilities found" "${SCAN_LOG}"; then
         cat "${SCAN_LOG}"
     fi
@@ -579,10 +564,8 @@ if [[ -n "${TAG_EXISTS}" ]]; then
     download_release_information
     verify_git_tags
     verify_git_tag_types
-    if [[ -n "${RELEASE_EXISTS}" ]]; then
-        verify_release_notes
-        verify_release_artefacts
-    fi
+    verify_release_notes
+    verify_release_artefacts
     verify_container_images
 fi
 
diff --git a/ironic-deployment/components/basic-auth/kustomization.yaml b/ironic-deployment/components/basic-auth/kustomization.yaml
index 8eaff16a..8c10974c 100644
--- a/ironic-deployment/components/basic-auth/kustomization.yaml
+++ b/ironic-deployment/components/basic-auth/kustomization.yaml
@@ -1,45 +1,21 @@
 apiVersion: kustomize.config.k8s.io/v1alpha1
 kind: Component
 
-# NOTE: This component requires secrets with the basic auth credentials and config!
-# How you create them is up to you.
-# The required secrets are:
-# - ironic-htpasswd
-# - ironic-inspector-htpasswd
-# - ironic-auth-config
-# - ironic-inspector-auth-config
-#
-# The content should be as in these examples:
-#
-# apiVersion: v1
-# kind: Secret
-# metadata:
-#   name: ironic-htpasswd
-# data:
-#   IRONIC_HTPASSWD: <base64-encoded-htpasswd-string>
-# ---
-# apiVersion: v1
-# kind: Secret
-# metadata:
-#   name: ironic-inspector-htpasswd
-# data:
-#   INSPECTOR_HTPASSWD: <base64-encoded-htpasswd-string>
-# ---
-# apiVersion: v1
-# kind: Secret
-# metadata:
-#   name: ironic-auth-config
-# data:
-#   auth-config: <base64-encoded-auth-config>
-# ---
-# apiVersion: v1
-# kind: Secret
-# metadata:
-#   name: ironic-inspector-auth-config
-# data:
-#   auth-config: <base64-encoded-auth-config>
-#
-# Check `ironic-auth-config-tpl` for a template of what to put in the auth-config.
+secretGenerator:
+- behavior: create
+  envs:
+  - ironic-htpasswd
+  name: ironic-htpasswd
+- behavior: create
+  envs:
+  - ironic-inspector-htpasswd
+  name: ironic-inspector-htpasswd
+- name: ironic-auth-config
+  files:
+  - auth-config=ironic-auth-config
+- name: ironic-inspector-auth-config
+  files:
+  - auth-config=ironic-inspector-auth-config
 
 patches:
-  - path: auth.yaml
+- path: auth.yaml
diff --git a/ironic-deployment/overlays/basic-auth_tls/kustomization.yaml b/ironic-deployment/overlays/basic-auth_tls/kustomization.yaml
index 9df46e96..0aa89cf5 100644
--- a/ironic-deployment/overlays/basic-auth_tls/kustomization.yaml
+++ b/ironic-deployment/overlays/basic-auth_tls/kustomization.yaml
@@ -14,19 +14,3 @@ components:
 # variables on ironic-httpd with this patch.
 patches:
 - path: basic-auth_tls.yaml
-# Example for how to generate the necessary secrets:
-# secretGenerator:
-# - behavior: create
-#   envs:
-#   - ironic-htpasswd
-#   name: ironic-htpasswd
-# - behavior: create
-#   envs:
-#   - ironic-inspector-htpasswd
-#   name: ironic-inspector-htpasswd
-# - name: ironic-auth-config
-#   files:
-#   - auth-config=ironic-auth-config
-# - name: ironic-inspector-auth-config
-#   files:
-#   - auth-config=ironic-inspector-auth-config
diff --git a/pkg/provisioner/ironic/hardwaredetails/hardwaredetails.go b/pkg/provisioner/ironic/hardwaredetails/hardwaredetails.go
index c1821977..6b480167 100644
--- a/pkg/provisioner/ironic/hardwaredetails/hardwaredetails.go
+++ b/pkg/provisioner/ironic/hardwaredetails/hardwaredetails.go
@@ -16,7 +16,7 @@ import (
 
 // GetHardwareDetails converts Ironic introspection data into BareMetalHost HardwareDetails.
 func GetHardwareDetails(data *nodes.InventoryData, logger logr.Logger) *metal3api.HardwareDetails {
-	ironicData, inspectorData, err := data.PluginData.GuessFormat()
+	inspectorData, err := data.PluginData.AsInspectorData()
 	if err != nil {
 		logger.Error(err, "cannot get plugin data from inventory, some fields will not be available")
 	}
@@ -25,18 +25,18 @@ func GetHardwareDetails(data *nodes.InventoryData, logger logr.Logger) *metal3ap
 	details.Firmware = getFirmwareDetails(data.Inventory.SystemVendor.Firmware)
 	details.SystemVendor = getSystemVendorDetails(data.Inventory.SystemVendor)
 	details.RAMMebibytes = data.Inventory.Memory.PhysicalMb
-	details.NIC = getNICDetails(data.Inventory.Interfaces, ironicData, inspectorData)
+	details.NIC = getNICDetails(data.Inventory.Interfaces, inspectorData.AllInterfaces)
 	details.Storage = getStorageDetails(data.Inventory.Disks)
 	details.CPU = getCPUDetails(&data.Inventory.CPU)
 	details.Hostname = data.Inventory.Hostname
 	return details
 }
 
-func getVLANs(lldp map[string]interface{}) (vlans []metal3api.VLAN, vlanid metal3api.VLANID) {
-	if lldp == nil {
+func getVLANs(intf introspection.BaseInterfaceType) (vlans []metal3api.VLAN, vlanid metal3api.VLANID) {
+	if intf.LLDPProcessed == nil {
 		return
 	}
-	if spvs, ok := lldp["switch_port_vlans"]; ok {
+	if spvs, ok := intf.LLDPProcessed["switch_port_vlans"]; ok {
 		if data, ok := spvs.([]map[string]interface{}); ok {
 			vlans = make([]metal3api.VLAN, len(data))
 			for i, vlan := range data {
@@ -49,28 +49,18 @@ func getVLANs(lldp map[string]interface{}) (vlans []metal3api.VLAN, vlanid metal
 			}
 		}
 	}
-	if vid, ok := lldp["switch_port_untagged_vlan_id"].(int); ok {
+	if vid, ok := intf.LLDPProcessed["switch_port_untagged_vlan_id"].(int); ok {
 		vlanid = metal3api.VLANID(vid)
 	}
 	return
 }
 
 func getNICDetails(ifdata []inventory.InterfaceType,
-	ironicData *inventory.StandardPluginData,
-	inspectorData *introspection.Data) []metal3api.NIC {
+	basedata map[string]introspection.BaseInterfaceType) []metal3api.NIC {
 	var nics []metal3api.NIC
 	for _, intf := range ifdata {
-		var lldp map[string]interface{}
-		var pxeEnabled bool
-		if ironicData != nil {
-			pxeEnabled = ironicData.AllInterfaces[intf.Name].PXEEnabled
-			lldp = ironicData.ParsedLLDP[intf.Name]
-		} else {
-			pxeEnabled = inspectorData.AllInterfaces[intf.Name].PXE
-			lldp = inspectorData.AllInterfaces[intf.Name].LLDPProcessed
-		}
-
-		vlans, vlanid := getVLANs(lldp)
+		baseIntf := basedata[intf.Name]
+		vlans, vlanid := getVLANs(baseIntf)
 		// We still store one nic even if both ips are unset
 		// if both are set, we store two nics with each ip
 		if intf.IPV4Address != "" || intf.IPV6Address == "" {
@@ -83,7 +73,7 @@ func getNICDetails(ifdata []inventory.InterfaceType,
 				VLANs:     vlans,
 				VLANID:    vlanid,
 				SpeedGbps: intf.SpeedMbps / 1000,
-				PXE:       pxeEnabled,
+				PXE:       baseIntf.PXE,
 			})
 		}
 		if intf.IPV6Address != "" {
@@ -96,7 +86,7 @@ func getNICDetails(ifdata []inventory.InterfaceType,
 				VLANs:     vlans,
 				VLANID:    vlanid,
 				SpeedGbps: intf.SpeedMbps / 1000,
-				PXE:       pxeEnabled,
+				PXE:       baseIntf.PXE,
 			})
 		}
 	}
diff --git a/pkg/provisioner/ironic/ironic.go b/pkg/provisioner/ironic/ironic.go
index 88ed19e0..58eadceb 100644
--- a/pkg/provisioner/ironic/ironic.go
+++ b/pkg/provisioner/ironic/ironic.go
@@ -8,10 +8,8 @@ import (
 
 	"github.com/go-logr/logr"
 	"github.com/pkg/errors"
-	"golang.org/x/exp/slices"
 
 	"github.com/gophercloud/gophercloud"
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/drivers"
 	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
 	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/ports"
 
@@ -317,19 +315,6 @@ func (p *ironicProvisioner) createPXEEnabledNodePort(uuid, macAddress string) er
 	return nil
 }
 
-func (p *ironicProvisioner) getInspectInterface(bmcAccess bmc.AccessDetails) (string, error) {
-	driver, err := drivers.GetDriverDetails(p.client, bmcAccess.Driver()).Extract()
-	if err != nil {
-		return "", fmt.Errorf("cannot load information about driver %s: %w", bmcAccess.Driver(), err)
-	}
-
-	if slices.Contains(driver.EnabledInspectInterfaces, "agent") {
-		return "agent", nil
-	}
-
-	return "inspector", nil // backward compatibility
-}
-
 // ValidateManagementAccess registers the host with the provisioning
 // system and tests the connection information for the host to verify
 // that the location and credentials work.
@@ -382,12 +367,6 @@ func (p *ironicProvisioner) ValidateManagementAccess(data provisioner.Management
 			return
 		}
 
-		inspectInterface, driverErr := p.getInspectInterface(bmcAccess)
-		if driverErr != nil {
-			result, err = transientError(driverErr)
-			return
-		}
-
 		nodeCreateOpts := nodes.CreateOpts{
 			Driver:              bmcAccess.Driver(),
 			BIOSInterface:       bmcAccess.BIOSInterface(),
@@ -395,7 +374,7 @@ func (p *ironicProvisioner) ValidateManagementAccess(data provisioner.Management
 			Name:                ironicNodeName(p.objectMeta),
 			DriverInfo:          driverInfo,
 			DeployInterface:     p.deployInterface(data),
-			InspectInterface:    inspectInterface,
+			InspectInterface:    "inspector",
 			ManagementInterface: bmcAccess.ManagementInterface(),
 			PowerInterface:      bmcAccess.PowerInterface(),
 			RAIDInterface:       bmcAccess.RAIDInterface(),
diff --git a/tools/deploy.sh b/tools/deploy.sh
index b4860062..b525d4e4 100755
--- a/tools/deploy.sh
+++ b/tools/deploy.sh
@@ -102,20 +102,47 @@ export NAMEPREFIX=${NAMEPREFIX:-"baremetal-operator"}
 
 SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
 IRONIC_BASIC_AUTH_COMPONENT="${SCRIPTDIR}/ironic-deployment/components/basic-auth"
-
-TEMP_BMO_OVERLAY="${SCRIPTDIR}/config/overlays/temp"
 TEMP_IRONIC_OVERLAY="${SCRIPTDIR}/ironic-deployment/overlays/temp"
-rm -rf "${TEMP_BMO_OVERLAY}"
 rm -rf "${TEMP_IRONIC_OVERLAY}"
-mkdir -p "${TEMP_BMO_OVERLAY}"
 mkdir -p "${TEMP_IRONIC_OVERLAY}"
 
 KUSTOMIZE="${SCRIPTDIR}/tools/bin/kustomize"
 make -C "$(dirname "$0")/.." "${KUSTOMIZE}"
 
-#
-# Generate credentials as needed
-#
+# Create a temporary overlay where we can make changes.
+pushd "${TEMP_IRONIC_OVERLAY}"
+${KUSTOMIZE} create --resources=../../../config/namespace \
+  --namespace=baremetal-operator-system --nameprefix=baremetal-operator-
+
+if [ "${DEPLOY_BASIC_AUTH}" == "true" ]; then
+    BMO_SCENARIO="${SCRIPTDIR}/config/basic-auth"
+    if [[ "${DEPLOY_TLS}" == "true" ]]; then
+        BMO_SCENARIO="${BMO_SCENARIO}/tls"
+        # Basic-auth + TLS is special since TLS also means reverse proxy, which affects basic-auth.
+        # Therefore we have an overlay that we use as base for this case.
+        ${KUSTOMIZE} edit add resource ../../overlays/basic-auth_tls
+    else
+        BMO_SCENARIO="${BMO_SCENARIO}/default"
+        ${KUSTOMIZE} edit add resource ../../base
+        ${KUSTOMIZE} edit add component ../../components/basic-auth
+    fi
+else
+    BMO_SCENARIO="${SCRIPTDIR}/config"
+    if [[ "${DEPLOY_TLS}" == "true" ]]; then
+        BMO_SCENARIO="${BMO_SCENARIO}/tls"
+        ${KUSTOMIZE} edit add component ../../components/tls
+    fi
+fi
+
+if [[ "${DEPLOY_KEEPALIVED}" == "true" ]]; then
+    ${KUSTOMIZE} edit add component ../../components/keepalived
+fi
+
+if [[ "${DEPLOY_MARIADB}" == "true" ]]; then
+    ${KUSTOMIZE} edit add component ../../components/mariadb
+fi
+
+popd
 
 IRONIC_DATA_DIR="${IRONIC_DATA_DIR:-/opt/metal3/ironic/}"
 IRONIC_AUTH_DIR="${IRONIC_AUTH_DIR:-"${IRONIC_DATA_DIR}auth/"}"
@@ -160,102 +187,30 @@ if [[ "${DEPLOY_BASIC_AUTH}" == "true" ]]; then
     fi
 
     if [[ "${DEPLOY_BMO}" == "true" ]]; then
-        echo "${IRONIC_USERNAME}" > "${TEMP_BMO_OVERLAY}/ironic-username"
-        echo "${IRONIC_PASSWORD}" > "${TEMP_BMO_OVERLAY}/ironic-password"
+        echo "${IRONIC_USERNAME}" > "${BMO_SCENARIO}/ironic-username"
+        echo "${IRONIC_PASSWORD}" > "${BMO_SCENARIO}/ironic-password"
 
-        echo "${IRONIC_INSPECTOR_USERNAME}" > "${TEMP_BMO_OVERLAY}/ironic-inspector-username"
-        echo "${IRONIC_INSPECTOR_PASSWORD}" > "${TEMP_BMO_OVERLAY}/ironic-inspector-password"
+        echo "${IRONIC_INSPECTOR_USERNAME}" > "${BMO_SCENARIO}/ironic-inspector-username"
+        echo "${IRONIC_INSPECTOR_PASSWORD}" > "${BMO_SCENARIO}/ironic-inspector-password"
     fi
 
     if [[ "${DEPLOY_IRONIC}" == "true" ]]; then
         envsubst < "${IRONIC_BASIC_AUTH_COMPONENT}/ironic-auth-config-tpl" > \
-        "${TEMP_IRONIC_OVERLAY}/ironic-auth-config"
+        "${IRONIC_BASIC_AUTH_COMPONENT}/ironic-auth-config"
         envsubst < "${IRONIC_BASIC_AUTH_COMPONENT}/ironic-inspector-auth-config-tpl" > \
-        "${TEMP_IRONIC_OVERLAY}/ironic-inspector-auth-config"
+        "${IRONIC_BASIC_AUTH_COMPONENT}/ironic-inspector-auth-config"
 
         echo "IRONIC_HTPASSWD=$(htpasswd -n -b -B "${IRONIC_USERNAME}" "${IRONIC_PASSWORD}")" > \
-        "${TEMP_IRONIC_OVERLAY}/ironic-htpasswd"
+        "${IRONIC_BASIC_AUTH_COMPONENT}/ironic-htpasswd"
         echo "INSPECTOR_HTPASSWD=$(htpasswd -n -b -B "${IRONIC_INSPECTOR_USERNAME}" \
-        "${IRONIC_INSPECTOR_PASSWORD}")" > "${TEMP_IRONIC_OVERLAY}/ironic-inspector-htpasswd"
+        "${IRONIC_INSPECTOR_PASSWORD}")" > "${IRONIC_BASIC_AUTH_COMPONENT}/ironic-inspector-htpasswd"
     fi
 fi
 
-#
-# Ironic
-#
-
-if [[ "${DEPLOY_IRONIC}" == "true" ]]; then
-    # Create a temporary overlay where we can make changes.
-    pushd "${TEMP_IRONIC_OVERLAY}"
-    ${KUSTOMIZE} create --resources=../../../config/namespace \
-    --namespace=baremetal-operator-system --nameprefix=baremetal-operator-
-
-    if [ "${DEPLOY_BASIC_AUTH}" == "true" ]; then
-        ${KUSTOMIZE} edit add secret ironic-htpasswd --from-env-file=ironic-htpasswd
-        ${KUSTOMIZE} edit add secret ironic-inspector-htpasswd --from-env-file=ironic-inspector-htpasswd
-        ${KUSTOMIZE} edit add secret ironic-auth-config --from-file=auth-config=ironic-auth-config
-        ${KUSTOMIZE} edit add secret ironic-inspector-auth-config --from-file=auth-config=ironic-inspector-auth-config
-
-        if [[ "${DEPLOY_TLS}" == "true" ]]; then
-            # Basic-auth + TLS is special since TLS also means reverse proxy, which affects basic-auth.
-            # Therefore we have an overlay that we use as base for this case.
-            ${KUSTOMIZE} edit add resource ../../overlays/basic-auth_tls
-        else
-            ${KUSTOMIZE} edit add resource ../../base
-            ${KUSTOMIZE} edit add component ../../components/basic-auth
-        fi
-    else
-        if [[ "${DEPLOY_TLS}" == "true" ]]; then
-            ${KUSTOMIZE} edit add component ../../components/tls
-        fi
-    fi
-
-    if [[ "${DEPLOY_KEEPALIVED}" == "true" ]]; then
-        ${KUSTOMIZE} edit add component ../../components/keepalived
-    fi
-
-    if [[ "${DEPLOY_MARIADB}" == "true" ]]; then
-        ${KUSTOMIZE} edit add component ../../components/mariadb
-    fi
-    popd
-fi
-
-#
-# BMO
-#
-
-if [[ "${DEPLOY_BMO}" == "true" ]]; then
-    # Create a temporary overlay where we can make changes.
-    pushd "${TEMP_BMO_OVERLAY}"
-    ${KUSTOMIZE} create --resources=../../base,../../namespace \
-    --namespace=baremetal-operator-system
-
-    if [ "${DEPLOY_BASIC_AUTH}" == "true" ]; then
-        ${KUSTOMIZE} edit add component ../../components/basic-auth
-        # These files are created below
-        ${KUSTOMIZE} edit add secret ironic-credentials \
-            --from-file=username=ironic-username --from-file=password=ironic-password
-        ${KUSTOMIZE} edit add secret ironic-inspector-credentials \
-            --from-file=username=ironic-inspector-username --from-file=password=ironic-inspector-password
-    fi
-
-    if [[ "${DEPLOY_TLS}" == "true" ]]; then
-        ${KUSTOMIZE} edit add component ../../components/tls
-    fi
-    popd
-fi
-
-#
-# Deploy
-#
-
 if [[ "${DEPLOY_BMO}" == "true" ]]; then
-    pushd "${TEMP_BMO_OVERLAY}"
-    # This is to keep the current behavior of using the ironic.env file for the configmap
-    cp "${SCRIPTDIR}/config/default/ironic.env" "${TEMP_BMO_OVERLAY}/ironic.env"
-    ${KUSTOMIZE} edit add configmap ironic --behavior=create --from-env-file=ironic.env
+    pushd "${SCRIPTDIR}"
     # shellcheck disable=SC2086
-    ${KUSTOMIZE} build "${TEMP_BMO_OVERLAY}" | kubectl apply ${KUBECTL_ARGS} -f -
+    ${KUSTOMIZE} build "${BMO_SCENARIO}" | kubectl apply ${KUBECTL_ARGS} -f -
     popd
 fi
 
@@ -294,23 +249,19 @@ if [[ "${DEPLOY_IRONIC}" == "true" ]]; then
     popd
 fi
 
-#
-# Cleanup
-#
-
 if [[ "${DEPLOY_BASIC_AUTH}" == "true" ]]; then
     if [[ "${DEPLOY_BMO}" == "true" ]]; then
-        rm "${TEMP_BMO_OVERLAY}/ironic-username"
-        rm "${TEMP_BMO_OVERLAY}/ironic-password"
-        rm "${TEMP_BMO_OVERLAY}/ironic-inspector-username"
-        rm "${TEMP_BMO_OVERLAY}/ironic-inspector-password"
+        rm "${BMO_SCENARIO}/ironic-username"
+        rm "${BMO_SCENARIO}/ironic-password"
+        rm "${BMO_SCENARIO}/ironic-inspector-username"
+        rm "${BMO_SCENARIO}/ironic-inspector-password"
     fi
 
     if [[ "${DEPLOY_IRONIC}" == "true" ]]; then
-        rm "${TEMP_IRONIC_OVERLAY}/ironic-auth-config"
-        rm "${TEMP_IRONIC_OVERLAY}/ironic-inspector-auth-config"
+        rm "${IRONIC_BASIC_AUTH_COMPONENT}/ironic-auth-config"
+        rm "${IRONIC_BASIC_AUTH_COMPONENT}/ironic-inspector-auth-config"
 
-        rm "${TEMP_IRONIC_OVERLAY}/ironic-htpasswd"
-        rm "${TEMP_IRONIC_OVERLAY}/ironic-inspector-htpasswd"
+        rm "${IRONIC_BASIC_AUTH_COMPONENT}/ironic-htpasswd"
+        rm "${IRONIC_BASIC_AUTH_COMPONENT}/ironic-inspector-htpasswd"
     fi
 fi


Test patch:
diff --git a/config/overlays/e2e/ironic.env b/config/overlays/e2e/ironic.env
index 24c556e1..2332d577 100644
--- a/config/overlays/e2e/ironic.env
+++ b/config/overlays/e2e/ironic.env
@@ -2,7 +2,7 @@ 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_ENDPOINT=http://192.168.222.199:6385/v1/
 CACHEURL=http://192.168.222.199/images
 IRONIC_FAST_TRACK=true
 IRONIC_KERNEL_PARAMS=console=ttyS0
diff --git a/config/overlays/e2e/kustomization.yaml b/config/overlays/e2e/kustomization.yaml
index 63c1e21e..c383a506 100644
--- a/config/overlays/e2e/kustomization.yaml
+++ b/config/overlays/e2e/kustomization.yaml
@@ -1,14 +1,15 @@
 apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
-namespace: baremetal-operator-system
+
 resources:
-- ../basic-auth_tls
+- ../../namespace
+- ../../default
 
 configMapGenerator:
-- name: ironic
-  behavior: create
+- behavior: replace
   envs:
   - ironic.env
+  name: ironic
 
 patches:
 - patch: |
@@ -23,19 +24,3 @@ patches:
 images:
 - name: quay.io/metal3-io/baremetal-operator
   newTag: e2e
-
-# 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/hack/ci-e2e.sh b/hack/ci-e2e.sh
index 1288f377..9bd9ac27 100755
--- a/hack/ci-e2e.sh
+++ b/hack/ci-e2e.sh
@@ -115,37 +115,13 @@ IMAGE_DIR="${REPO_ROOT}/test/e2e/images"
 ## Download and run image server
 mkdir -p "${IMAGE_DIR}"
 pushd "${IMAGE_DIR}"
-wget --quiet https://artifactory.nordix.org/artifactory/metal3/images/iso/"${IMAGE_FILE}"
+wget --quiet "https://download.cirros-cloud.net/${CIRROS_VERSION}/${IMAGE_FILE}"
 popd
 
 docker run --name image-server-e2e -d \
   -p 80:8080 \
   -v "${IMAGE_DIR}:/usr/share/nginx/html" nginxinc/nginx-unprivileged
 
-# Generate credentials
-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)"
-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)"
-
-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"
-
-envsubst < "${REPO_ROOT}/ironic-deployment/components/basic-auth/ironic-auth-config-tpl" > \
-  "${IRONIC_OVERLAY}/ironic-auth-config"
-envsubst < "${REPO_ROOT}/ironic-deployment/components/basic-auth/ironic-inspector-auth-config-tpl" > \
-  "${IRONIC_OVERLAY}/ironic-inspector-auth-config"
-
-echo "IRONIC_HTPASSWD=$(htpasswd -n -b -B "${IRONIC_USERNAME}" "${IRONIC_PASSWORD}")" > \
-  "${IRONIC_OVERLAY}/ironic-htpasswd"
-echo "INSPECTOR_HTPASSWD=$(htpasswd -n -b -B "${IRONIC_INSPECTOR_USERNAME}" \
-  "${IRONIC_INSPECTOR_PASSWORD}")" > "${IRONIC_OVERLAY}/ironic-inspector-htpasswd"
-
 # We need to gather artifacts/logs before exiting also if there are errors
 set +e
 
diff --git a/hack/clean-e2e.sh b/hack/clean-e2e.sh
index 06d29ceb..75c4a597 100755
--- a/hack/clean-e2e.sh
+++ b/hack/clean-e2e.sh
@@ -8,10 +8,10 @@ docker rm -f vbmc
 docker rm -f image-server-e2e
 docker rm -f sushy-tools
 virsh -c qemu:///system destroy --domain bmo-e2e-0
-virsh -c qemu:///system undefine --domain bmo-e2e-0 --nvram --remove-all-storage
+virsh -c qemu:///system undefine --domain bmo-e2e-0 --remove-all-storage
 virsh -c qemu:///system net-destroy baremetal-e2e
 virsh -c qemu:///system net-undefine baremetal-e2e
 
-rm -rf "${REPO_ROOT}/test/e2e/_artifacts"
-rm -rf "${REPO_ROOT}/artifacts.tar.gz"
-rm -rf "${REPO_ROOT}/test/e2e/images"
+rm -rfv "${REPO_ROOT}/test/e2e/_artifacts"
+rm -rfv "${REPO_ROOT}/artifacts.tar.gz"
+rm -rfv "${REPO_ROOT}/test/e2e/images"
diff --git a/hack/e2e/ensure_go.sh b/hack/e2e/ensure_go.sh
index 9d7507cc..8a920935 100755
--- a/hack/e2e/ensure_go.sh
+++ b/hack/e2e/ensure_go.sh
@@ -2,7 +2,7 @@
 
 set -eux
 
-MINIMUM_GO_VERSION=go1.20.11
+MINIMUM_GO_VERSION=go1.20.10
 
 # Ensure the go tool exists and is a viable version, or installs it
 verify_go_version()
diff --git a/hack/e2e/ensure_minikube.sh b/hack/e2e/ensure_minikube.sh
index 9fc3b522..5e7d1980 100755
--- a/hack/e2e/ensure_minikube.sh
+++ b/hack/e2e/ensure_minikube.sh
@@ -20,7 +20,7 @@ verify_minikube_version() {
   fi
   local minikube_version
   minikube_version="$(minikube version --short)"
-  if [[ "${MINIMUM_MINIKUBE_VERSION}" != $(echo -e "${MINIMUM_MINIKUBE_VERSION}\n${minikube_version}" | sort -V | head -n1) ]]; then
+  if [[ "${MINIMUM_MINIKUBE_VERSION}" != "${minikube_version}" ]]; then
       cat << EOF
 Detected minikube version: ${minikube_version}.
 Requires ${MINIMUM_MINIKUBE_VERSION} or greater.
diff --git a/hack/e2e/net.xml b/hack/e2e/net.xml
index 54a2740b..f64fd04f 100644
--- a/hack/e2e/net.xml
+++ b/hack/e2e/net.xml
@@ -9,8 +9,7 @@
   <ip address='192.168.222.1' netmask='255.255.255.0'>
     <dhcp>
       <range start='192.168.222.2' end='192.168.222.199'/>
-      <host mac='52:54:00:6c:3c:01' name='minikube' ip='192.168.222.199'/>
-      <host mac='00:60:2f:31:81:01' name='bmo-e2e-0' ip='192.168.222.122'/>
+      <host mac='52:54:00:6c:3c:01' name='vm1' ip='192.168.222.199'/>
       <bootp file='http://192.168.222.199:6180/boot.ipxe'/>
     </dhcp>
   </ip>
diff --git a/ironic-deployment/overlays/e2e/ironic_bmo_configmap.env b/ironic-deployment/overlays/e2e/ironic_bmo_configmap.env
index 24c556e1..2332d577 100644
--- a/ironic-deployment/overlays/e2e/ironic_bmo_configmap.env
+++ b/ironic-deployment/overlays/e2e/ironic_bmo_configmap.env
@@ -2,7 +2,7 @@ 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_ENDPOINT=http://192.168.222.199:6385/v1/
 CACHEURL=http://192.168.222.199/images
 IRONIC_FAST_TRACK=true
 IRONIC_KERNEL_PARAMS=console=ttyS0
diff --git a/ironic-deployment/overlays/e2e/kustomization.yaml b/ironic-deployment/overlays/e2e/kustomization.yaml
index 7710dbc3..2f2978f1 100644
--- a/ironic-deployment/overlays/e2e/kustomization.yaml
+++ b/ironic-deployment/overlays/e2e/kustomization.yaml
@@ -1,51 +1,15 @@
 apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
-namespace: baremetal-operator-system
+
 resources:
 - ../../../config/namespace
-- ../../base
-
-components:
-- ../../components/basic-auth
-- ../../components/tls
+- ../../default
 
 configMapGenerator:
 - envs:
   - ironic_bmo_configmap.env
   name: ironic-bmo-configmap
-  behavior: create
+  behavior: replace
 
 patches:
   - path: ironic-patch.yaml
-
-# NOTE: These credentials are generated automatically in hack/ci-e2e.sh
-secretGenerator:
-- name: ironic-htpasswd
-  behavior: create
-  envs:
-  - ironic-htpasswd
-- name: ironic-inspector-htpasswd
-  behavior: create
-  envs:
-  - ironic-inspector-htpasswd
-- name: ironic-auth-config
-  files:
-  - auth-config=ironic-auth-config
-- name: ironic-inspector-auth-config
-  files:
-  - auth-config=ironic-inspector-auth-config
-
-replacements:
-  # Replace IRONIC_HOST_IP in certificates with the PROVISIONING_IP from the configmap
-  - source:
-      kind: ConfigMap
-      name: ironic-bmo-configmap
-      fieldPath: .data.PROVISIONING_IP
-    targets:
-      - select:
-          version: v1
-          group: cert-manager.io
-          kind: Certificate
-          name:
-        fieldPaths:
-          - .spec.ipAddresses.0
diff --git a/pkg/provisioner/ironic/hardwaredetails/hardwaredetails_test.go b/pkg/provisioner/ironic/hardwaredetails/hardwaredetails_test.go
index c77eb035..a3c68b64 100644
--- a/pkg/provisioner/ironic/hardwaredetails/hardwaredetails_test.go
+++ b/pkg/provisioner/ironic/hardwaredetails/hardwaredetails_test.go
@@ -6,24 +6,25 @@ import (
 
 	"github.com/gophercloud/gophercloud/openstack/baremetal/inventory"
 	"github.com/gophercloud/gophercloud/openstack/baremetalintrospection/v1/introspection"
-	"github.com/stretchr/testify/assert"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
 )
 
 func TestGetVLANs(t *testing.T) {
-	vlans, vid := getVLANs(map[string]interface{}{
-		"switch_port_vlans": []map[string]interface{}{
-			{
-				"id":   1,
-				"name": "vlan1",
-			},
-			{
-				"id":   4094,
-				"name": "vlan4094",
+	vlans, vid := getVLANs(introspection.BaseInterfaceType{
+		LLDPProcessed: map[string]interface{}{
+			"switch_port_vlans": []map[string]interface{}{
+				{
+					"id":   1,
+					"name": "vlan1",
+				},
+				{
+					"id":   4094,
+					"name": "vlan4094",
+				},
 			},
+			"switch_port_untagged_vlan_id": 1,
 		},
-		"switch_port_untagged_vlan_id": 1,
 	})
 	if vid != 1 {
 		t.Errorf("Unexpected untagged VLAN ID %d", vid)
@@ -40,29 +41,31 @@ func TestGetVLANs(t *testing.T) {
 }
 
 func TestGetVLANsMalformed(t *testing.T) {
-	vlans, vid := getVLANs(map[string]interface{}{
-		"switch_port_vlans": []map[string]interface{}{
-			{
-				"foo":  "bar",
-				"name": "vlan1",
-			},
-			{
-				"foo": "bar",
-				"id":  1,
-			},
-			{
-				"name": "vlan2",
-				"id":   "2",
-			},
-			{
-				"name": 3,
-				"id":   3,
-			},
-			{
-				"foo": "bar",
+	vlans, vid := getVLANs(introspection.BaseInterfaceType{
+		LLDPProcessed: map[string]interface{}{
+			"switch_port_vlans": []map[string]interface{}{
+				{
+					"foo":  "bar",
+					"name": "vlan1",
+				},
+				{
+					"foo": "bar",
+					"id":  1,
+				},
+				{
+					"name": "vlan2",
+					"id":   "2",
+				},
+				{
+					"name": 3,
+					"id":   3,
+				},
+				{
+					"foo": "bar",
+				},
 			},
+			"switch_port_untagged_vlan_id": "1",
 		},
-		"switch_port_untagged_vlan_id": "1",
 	})
 	if vid != 0 {
 		t.Errorf("Unexpected untagged VLAN ID %d", vid)
@@ -86,11 +89,27 @@ func TestGetVLANsMalformed(t *testing.T) {
 		t.Errorf("Unexpected VLAN %d %s", vlans[0].ID, vlans[0].Name)
 	}
 
-	vlans, vid = getVLANs(map[string]interface{}{
-		"switch_port_vlans": map[string]interface{}{
-			"foo": "bar",
+	vlans, vid = getVLANs(introspection.BaseInterfaceType{
+		LLDPProcessed: map[string]interface{}{
+			"switch_port_vlans": map[string]interface{}{
+				"foo": "bar",
+			},
+			"switch_port_untagged_vlan_id": "1",
+		},
+	})
+	if vid != 0 {
+		t.Errorf("Unexpected untagged VLAN ID %d", vid)
+	}
+	if len(vlans) != 0 {
+		t.Errorf("Expected 0 VLANs, got %d", len(vlans))
+	}
+
+	vlans, vid = getVLANs(introspection.BaseInterfaceType{
+		LLDPProcessed: map[string]interface{}{
+			"switch_port_vlans": []interface{}{
+				"foo",
+			},
 		},
-		"switch_port_untagged_vlan_id": "1",
 	})
 	if vid != 0 {
 		t.Errorf("Unexpected untagged VLAN ID %d", vid)
@@ -99,9 +118,9 @@ func TestGetVLANsMalformed(t *testing.T) {
 		t.Errorf("Expected 0 VLANs, got %d", len(vlans))
 	}
 
-	vlans, vid = getVLANs(map[string]interface{}{
-		"switch_port_vlans": []interface{}{
-			"foo",
+	vlans, vid = getVLANs(introspection.BaseInterfaceType{
+		LLDPProcessed: map[string]interface{}{
+			"switch_port_vlans": "foo",
 		},
 	})
 	if vid != 0 {
@@ -111,8 +130,8 @@ func TestGetVLANsMalformed(t *testing.T) {
 		t.Errorf("Expected 0 VLANs, got %d", len(vlans))
 	}
 
-	vlans, vid = getVLANs(map[string]interface{}{
-		"switch_port_vlans": "foo",
+	vlans, vid = getVLANs(introspection.BaseInterfaceType{
+		LLDPProcessed: map[string]interface{}{},
 	})
 	if vid != 0 {
 		t.Errorf("Unexpected untagged VLAN ID %d", vid)
@@ -121,7 +140,7 @@ func TestGetVLANsMalformed(t *testing.T) {
 		t.Errorf("Expected 0 VLANs, got %d", len(vlans))
 	}
 
-	vlans, vid = getVLANs(map[string]interface{}{})
+	vlans, vid = getVLANs(introspection.BaseInterfaceType{})
 	if vid != 0 {
 		t.Errorf("Unexpected untagged VLAN ID %d", vid)
 	}
@@ -130,26 +149,28 @@ func TestGetVLANsMalformed(t *testing.T) {
 	}
 }
 
-func TestGetNICDetailsInspector(t *testing.T) {
-	ironicData := inventory.StandardPluginData{
-		AllInterfaces: map[string]inventory.ProcessedInterfaceType{
-			"eth0": {
-				PXEEnabled: true,
-			},
-		},
-		ParsedLLDP: map[string]inventory.ParsedLLDP{
-			"eth0": {
-				"switch_port_vlans": []map[string]interface{}{
-					{
-						"id": 1,
-					},
-				},
-				"switch_port_untagged_vlan_id": 1,
-			},
+func TestGetNICDetails(t *testing.T) {
+	nics := getNICDetails(
+		[]inventory.InterfaceType{
+			{
+				Name:        "eth0",
+				IPV4Address: "192.0.2.1",
+				MACAddress:  "00:11:22:33:44:55"},
+			{
+				Name:        "eth1",
+				IPV6Address: "2001:db8::1",
+				MACAddress:  "66:77:88:99:aa:bb",
+				SpeedMbps:   1000},
+			{
+				Name:        "eth46",
+				IPV6Address: "2001:db8::2",
+				IPV4Address: "192.0.2.2",
+				MACAddress:  "00:11:22:33:44:66"},
+			{
+				Name:       "ethNoIp",
+				MACAddress: "00:11:22:33:44:77"},
 		},
-	}
-	inspectorData := introspection.Data{
-		AllInterfaces: map[string]introspection.BaseInterfaceType{
+		map[string]introspection.BaseInterfaceType{
 			"eth0": {
 				PXE: true,
 				LLDPProcessed: map[string]interface{}{
@@ -161,91 +182,51 @@ func TestGetNICDetailsInspector(t *testing.T) {
 					"switch_port_untagged_vlan_id": 1,
 				},
 			},
-		},
-	}
-	interfaces := []inventory.InterfaceType{
-		{
-			Name:        "eth0",
-			IPV4Address: "192.0.2.1",
-			MACAddress:  "00:11:22:33:44:55"},
-		{
-			Name:        "eth1",
-			IPV6Address: "2001:db8::1",
-			MACAddress:  "66:77:88:99:aa:bb",
-			SpeedMbps:   1000},
-		{
-			Name:        "eth46",
-			IPV6Address: "2001:db8::2",
-			IPV4Address: "192.0.2.2",
-			MACAddress:  "00:11:22:33:44:66"},
-		{
-			Name:       "ethNoIp",
-			MACAddress: "00:11:22:33:44:77"},
-	}
+		})
 
-	cases := []struct {
-		name          string
-		ironicData    *inventory.StandardPluginData
-		inspectorData *introspection.Data
-	}{
-		{
-			name:          "with-ironic",
-			ironicData:    &ironicData,
-			inspectorData: nil,
-		},
-		{
-			name:          "with-inspector",
-			ironicData:    nil,
-			inspectorData: &inspectorData,
+	// 5 expected because eth46 results in two items
+	if len(nics) != 5 {
+		t.Errorf("Expected 5 NICs, got %d", len(nics))
+	}
+	if (!reflect.DeepEqual(nics[0], metal3api.NIC{
+		Name: "eth0",
+		MAC:  "00:11:22:33:44:55",
+		IP:   "192.0.2.1",
+		PXE:  true,
+		VLANs: []metal3api.VLAN{
+			{ID: 1},
 		},
-	}
-	for _, tc := range cases {
-		t.Run(tc.name, func(t *testing.T) {
-			nics := getNICDetails(interfaces, tc.ironicData, tc.inspectorData)
-
-			// 5 expected because eth46 results in two items
-			assert.Len(t, nics, 5)
-			if (!reflect.DeepEqual(nics[0], metal3api.NIC{
-				Name: "eth0",
-				MAC:  "00:11:22:33:44:55",
-				IP:   "192.0.2.1",
-				PXE:  true,
-				VLANs: []metal3api.VLAN{
-					{ID: 1},
-				},
-				VLANID: 1,
-			})) {
-				t.Errorf("Unexpected NIC data")
-			}
-			if (!reflect.DeepEqual(nics[1], metal3api.NIC{
-				Name:      "eth1",
-				MAC:       "66:77:88:99:aa:bb",
-				IP:        "2001:db8::1",
-				SpeedGbps: 1,
-			})) {
-				t.Errorf("Unexpected NIC data")
-			}
-			if (!reflect.DeepEqual(nics[2], metal3api.NIC{
-				Name: "eth46",
-				MAC:  "00:11:22:33:44:66",
-				IP:   "192.0.2.2",
-			})) {
-				t.Errorf("Unexpected NIC data")
-			}
-			if (!reflect.DeepEqual(nics[3], metal3api.NIC{
-				Name: "eth46",
-				MAC:  "00:11:22:33:44:66",
-				IP:   "2001:db8::2",
-			})) {
-				t.Errorf("Unexpected NIC data")
-			}
-			if (!reflect.DeepEqual(nics[4], metal3api.NIC{
-				Name: "ethNoIp",
-				MAC:  "00:11:22:33:44:77",
-			})) {
-				t.Errorf("Unexpected NIC data")
-			}
-		})
+		VLANID: 1,
+	})) {
+		t.Errorf("Unexpected NIC data")
+	}
+	if (!reflect.DeepEqual(nics[1], metal3api.NIC{
+		Name:      "eth1",
+		MAC:       "66:77:88:99:aa:bb",
+		IP:        "2001:db8::1",
+		SpeedGbps: 1,
+	})) {
+		t.Errorf("Unexpected NIC data")
+	}
+	if (!reflect.DeepEqual(nics[2], metal3api.NIC{
+		Name: "eth46",
+		MAC:  "00:11:22:33:44:66",
+		IP:   "192.0.2.2",
+	})) {
+		t.Errorf("Unexpected NIC data")
+	}
+	if (!reflect.DeepEqual(nics[3], metal3api.NIC{
+		Name: "eth46",
+		MAC:  "00:11:22:33:44:66",
+		IP:   "2001:db8::2",
+	})) {
+		t.Errorf("Unexpected NIC data")
+	}
+	if (!reflect.DeepEqual(nics[4], metal3api.NIC{
+		Name: "ethNoIp",
+		MAC:  "00:11:22:33:44:77",
+	})) {
+		t.Errorf("Unexpected NIC data")
 	}
 }
 
diff --git a/pkg/provisioner/ironic/testserver/ironic.go b/pkg/provisioner/ironic/testserver/ironic.go
index 8cb9b09a..85a6dcb3 100644
--- a/pkg/provisioner/ironic/testserver/ironic.go
+++ b/pkg/provisioner/ironic/testserver/ironic.go
@@ -51,7 +51,6 @@ func (m *IronicMock) WithDefaultResponses() *IronicMock {
 	m.AddDefaultResponse("/v1/nodes/{id}/states/power", "", http.StatusAccepted, "{}")
 	m.AddDefaultResponse("/v1/nodes/{id}/states/raid", "", http.StatusNoContent, "{}")
 	m.AddDefaultResponse("/v1/nodes/{id}/validate", "", http.StatusOK, validateResult)
-	m.AddDefaultResponse("/v1/drivers/{driver}", "", http.StatusOK, "{}")
 
 	return m
 }
@@ -80,24 +79,18 @@ func (m *IronicMock) WithDrivers() *IronicMock {
 			],
 			"links": [
 			  {
-				"href": "http://[fd00:1101::3]:6385/v1/drivers/test",
+				"href": "http://[fd00:1101::3]:6385/v1/drivers/fake-hardware",
 				"rel": "self"
 			  },
 			  {
-				"href": "http://[fd00:1101::3]:6385/drivers/test",
+				"href": "http://[fd00:1101::3]:6385/drivers/fake-hardware",
 				"rel": "bookmark"
 			  }
 			],
-			"name": "test"
+			"name": "fake-hardware"
 		}]
 	}
 	`, http.StatusOK)
-	m.ResponseWithCode("/v1/drivers/test", `
-	{
-	    "enabled_deploy_interfaces": ["direct", "ramdisk", "custom-agent"],
-	    "enabled_inspect_interfaces": ["agent", "inspector", "no-inspect"]
-	}
-	`, http.StatusOK)
 	return m
 }
 
diff --git a/pkg/provisioner/ironic/validatemanagementaccess_test.go b/pkg/provisioner/ironic/validatemanagementaccess_test.go
index eb1f99e6..5a73c0c3 100644
--- a/pkg/provisioner/ironic/validatemanagementaccess_test.go
+++ b/pkg/provisioner/ironic/validatemanagementaccess_test.go
@@ -50,7 +50,6 @@ func TestValidateManagementAccessMACOptional(t *testing.T) {
 
 	// Set up ironic server to return the node
 	ironic := testserver.NewIronic(t).
-		WithDrivers().
 		Node(nodes.Node{
 			Name: host.Namespace + nameSeparator + host.Name,
 			UUID: host.Status.Provisioning.ID,
@@ -87,47 +86,8 @@ func TestValidateManagementAccessCreateNodeNoImage(t *testing.T) {
 		createdNode = &node
 	}
 
-	ironic := testserver.NewIronic(t).WithDrivers().CreateNodes(createCallback).NoNode(host.Namespace + nameSeparator + host.Name).NoNode(host.Name)
-	ironic.AddDefaultResponse("/v1/nodes/node-0", "PATCH", http.StatusOK, "{}")
-	ironic.Start()
-	defer ironic.Stop()
-
-	auth := clients.AuthConfig{Type: clients.NoAuth}
-	prov, err := newProvisionerWithSettings(host, bmc.Credentials{}, nullEventPublisher, ironic.Endpoint(), auth)
-	if err != nil {
-		t.Fatalf("could not create provisioner: %s", err)
-	}
-
-	result, provID, err := prov.ValidateManagementAccess(provisioner.ManagementAccessData{}, false, false)
-	if err != nil {
-		t.Fatalf("error from ValidateManagementAccess: %s", err)
-	}
-	assert.Equal(t, "", result.ErrorMessage)
-	assert.NotEqual(t, "", createdNode.UUID)
-	assert.Equal(t, createdNode.UUID, provID)
-	assert.Equal(t, createdNode.DeployInterface, "")
-	assert.Equal(t, "agent", createdNode.InspectInterface)
-}
-
-func TestValidateManagementAccessCreateNodeOldInspection(t *testing.T) {
-	// Create a host without a bootMACAddress and with a BMC that
-	// does not require one.
-	host := makeHost()
-	host.Spec.BootMACAddress = ""
-	host.Spec.Image = nil
-	host.Status.Provisioning.ID = "" // so we don't lookup by uuid
-
-	var createdNode *nodes.Node
-
-	createCallback := func(node nodes.Node) {
-		createdNode = &node
-	}
-
 	ironic := testserver.NewIronic(t).CreateNodes(createCallback).NoNode(host.Namespace + nameSeparator + host.Name).NoNode(host.Name)
 	ironic.AddDefaultResponse("/v1/nodes/node-0", "PATCH", http.StatusOK, "{}")
-	ironic.AddDefaultResponse("/v1/drivers/test", "GET", 200, `
-	    {"enabled_inspect_interfaces": ["inspector", "no-inspect"]}
-	`)
 	ironic.Start()
 	defer ironic.Stop()
 
@@ -144,7 +104,7 @@ func TestValidateManagementAccessCreateNodeOldInspection(t *testing.T) {
 	assert.Equal(t, "", result.ErrorMessage)
 	assert.NotEqual(t, "", createdNode.UUID)
 	assert.Equal(t, createdNode.UUID, provID)
-	assert.Equal(t, "inspector", createdNode.InspectInterface)
+	assert.Equal(t, createdNode.DeployInterface, "")
 }
 
 func TestValidateManagementAccessCreateWithImage(t *testing.T) {
@@ -160,7 +120,7 @@ func TestValidateManagementAccessCreateWithImage(t *testing.T) {
 		createdNode = &node
 	}
 
-	ironic := testserver.NewIronic(t).WithDrivers().CreateNodes(createCallback).NoNode(host.Namespace + nameSeparator + host.Name).NoNode(host.Name)
+	ironic := testserver.NewIronic(t).CreateNodes(createCallback).NoNode(host.Namespace + nameSeparator + host.Name).NoNode(host.Name)
 	ironic.AddDefaultResponse("/v1/nodes/node-0", "PATCH", http.StatusOK, "{}")
 	ironic.Start()
 	defer ironic.Stop()
@@ -196,7 +156,7 @@ func TestValidateManagementAccessCreateWithLiveIso(t *testing.T) {
 		createdNode = &node
 	}
 
-	ironic := testserver.NewIronic(t).WithDrivers().CreateNodes(createCallback).NoNode(host.Namespace + nameSeparator + host.Name).NoNode(host.Name)
+	ironic := testserver.NewIronic(t).CreateNodes(createCallback).NoNode(host.Namespace + nameSeparator + host.Name).NoNode(host.Name)
 	ironic.AddDefaultResponse("/v1/nodes/node-0", "PATCH", http.StatusOK, "{}")
 	ironic.Start()
 	defer ironic.Stop()
diff --git a/test/e2e/common.go b/test/e2e/common.go
index 4e96b6ab..3913d576 100644
--- a/test/e2e/common.go
+++ b/test/e2e/common.go
@@ -8,8 +8,6 @@ import (
 	"strings"
 	"time"
 
-	"golang.org/x/crypto/ssh"
-
 	"github.com/pkg/errors"
 	"gopkg.in/yaml.v2"
 
@@ -21,8 +19,6 @@ import (
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
 
-	capm3_e2e "github.com/metal3-io/cluster-api-provider-metal3/test/e2e"
-
 	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/cluster-api/test/framework"
 
@@ -300,62 +296,3 @@ func CreateBMHCredentialsSecret(ctx context.Context, client client.Client, secre
 
 	return nil
 }
-
-func executeSSHCommand(client *ssh.Client, command string) (string, error) {
-	session, err := client.NewSession()
-	if err != nil {
-		return "", fmt.Errorf("failed to create SSH session: %v", err)
-	}
-	defer session.Close()
-
-	output, err := session.CombinedOutput(command)
-	if err != nil {
-		return "", fmt.Errorf("failed to execute command '%s': %v", command, err)
-	}
-
-	return string(output), nil
-}
-
-// HasRootOnDisk parses the output from 'df -h' and checks if the root filesystem is on a disk (as opposed to tmpfs).
-func HasRootOnDisk(output string) bool {
-	lines := strings.Split(output, "\n")
-
-	for _, line := range lines[1:] { // Skip header line
-		if line == "" {
-			continue
-		}
-
-		fields := strings.Fields(line)
-		if len(fields) < 6 {
-			continue // Skip malformed lines
-		}
-
-		if fields[5] == "/" && !strings.Contains(fields[0], "tmpfs") {
-			return true // Found a non-tmpfs root filesystem
-		}
-	}
-
-	return false
-}
-
-// IsBootedFromDisk checks if the system, accessed via the provided ssh.Client, is booted
-// from a disk. It executes the 'df -h' command on the remote system to analyze the filesystem
-// layout. In the case of a disk boot, the output includes a disk-based root filesystem
-// (e.g., '/dev/vda1'). Conversely, in the case of a Live-ISO boot, the primary filesystems
-// are memory-based (tmpfs).
-func IsBootedFromDisk(client *ssh.Client) (bool, error) {
-	cmd := "df -h"
-	output, err := executeSSHCommand(client, cmd)
-	if err != nil {
-		return false, fmt.Errorf("error executing 'df -h': %w", err)
-	}
-
-	isDisk := HasRootOnDisk(output)
-	if isDisk {
-		capm3_e2e.Logf("System is booted from a disk.")
-	} else {
-		capm3_e2e.Logf("System is booted from a live ISO.")
-	}
-
-	return isDisk, nil
-}
diff --git a/test/e2e/config/fixture.yaml b/test/e2e/config/fixture.yaml
index afa67fef..ac5507c6 100644
--- a/test/e2e/config/fixture.yaml
+++ b/test/e2e/config/fixture.yaml
@@ -24,8 +24,7 @@ variables:
   BOOT_MAC_ADDRESS: "00:60:2f:31:81:01"
   IMAGE_URL: "http://192.168.222.1/cirros-0.6.2-x86_64-disk.img"
   IMAGE_CHECKSUM: "c8fc807773e5354afe61636071771906"
-  CERT_MANAGER_VERSION: "v1.13.1"
-  SSH_CHECK_PROVISIONED: "false"
+  CERT_MANAGER_VERSION: "v1.13.0"
 
 intervals:
   inspection/wait-unmanaged: ["1m", "10ms"]
diff --git a/test/e2e/config/ironic.yaml b/test/e2e/config/ironic.yaml
index b7d293a4..7c930b76 100644
--- a/test/e2e/config/ironic.yaml
+++ b/test/e2e/config/ironic.yaml
@@ -19,7 +19,7 @@ variables:
   DEPLOY_CERT_MANAGER: "true"
   BMO_KUSTOMIZATION: "../../config/overlays/e2e"
   IRONIC_KUSTOMIZATION: "../../ironic-deployment/overlays/e2e"
-  EXPECTED_HOST_NAME: "bmo-e2e-0"
+  EXPECTED_HOST_NAME: "localhost.localdomain"
   # Test credentials. The tests will create a BMH with these.
   BMC_USER: admin
   BMC_PASSWORD: password
@@ -31,10 +31,7 @@ variables:
   BOOT_MAC_ADDRESS: "00:60:2f:31:81:01"
   IMAGE_URL: "http://192.168.222.1/cirros-0.6.2-x86_64-disk.img"
   IMAGE_CHECKSUM: "c8fc807773e5354afe61636071771906"
-  CERT_MANAGER_VERSION: "v1.13.1"
-  SSH_CHECK_PROVISIONED: "true"
-  IP_BMO_E2E_0: "192.168.222.122"
-  SSH_PORT: "22"
+  CERT_MANAGER_VERSION: "v1.13.0"
 
 intervals:
   inspection/wait-unmanaged: ["1m", "5s"]
@@ -52,4 +49,3 @@ intervals:
   default/wait-deprovisioning: ["1m", "10ms"]
   default/wait-deleted: ["20s", "10ms"]
   default/wait-secret-deletion: ["1m", "1s"]
-  default/wait-connect-ssh: ["2m", "10s"]
diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go
index 60c7dcb0..d054d8c8 100644
--- a/test/e2e/e2e_suite_test.go
+++ b/test/e2e/e2e_suite_test.go
@@ -116,63 +116,63 @@ var _ = SynchronizedBeforeSuite(func() []byte {
 		}
 	}
 
-	if e2eConfig.GetVariable("DEPLOY_IRONIC") != "false" {
-		// Install Ironic
-		By("Installing Ironic")
-		kustomization := e2eConfig.GetVariable("IRONIC_KUSTOMIZATION")
+	if e2eConfig.GetVariable("DEPLOY_BMO") != "false" {
+		// Install BMO
+		By("Installing BMO")
+		kustomization := e2eConfig.GetVariable("BMO_KUSTOMIZATION")
 		manifest, err := buildKustomizeManifest(kustomization)
 		Expect(err).NotTo(HaveOccurred())
 		err = clusterProxy.Apply(ctx, manifest)
 		Expect(err).NotTo(HaveOccurred())
 
-		ironicDeployment := &v1.Deployment{
+		bmoDeployment := &v1.Deployment{
 			ObjectMeta: metav1.ObjectMeta{
-				Name:      "ironic",
+				Name:      "baremetal-operator-controller-manager",
 				Namespace: "baremetal-operator-system",
 			},
 		}
 		// Wait for it to become available
 		framework.WaitForDeploymentsAvailable(ctx, framework.WaitForDeploymentsAvailableInput{
 			Getter:     clusterProxy.GetClient(),
-			Deployment: ironicDeployment,
-		}, e2eConfig.GetIntervals("ironic", "wait-deployment")...)
+			Deployment: bmoDeployment,
+		}, e2eConfig.GetIntervals("default", "wait-deployment")...)
 		// Set up log watcher
 		framework.WatchDeploymentLogsByName(ctx, framework.WatchDeploymentLogsByNameInput{
 			GetLister:  clusterProxy.GetClient(),
 			Cache:      clusterProxy.GetCache(ctx),
 			ClientSet:  clusterProxy.GetClientSet(),
-			Deployment: ironicDeployment,
-			LogPath:    filepath.Join(artifactFolder, "logs", ironicDeployment.GetNamespace()),
+			Deployment: bmoDeployment,
+			LogPath:    filepath.Join(artifactFolder, "logs", bmoDeployment.GetNamespace()),
 		})
 	}
 
-	if e2eConfig.GetVariable("DEPLOY_BMO") != "false" {
-		// Install BMO
-		By("Installing BMO")
-		kustomization := e2eConfig.GetVariable("BMO_KUSTOMIZATION")
+	if e2eConfig.GetVariable("DEPLOY_IRONIC") != "false" {
+		// Install Ironic
+		By("Installing Ironic")
+		kustomization := e2eConfig.GetVariable("IRONIC_KUSTOMIZATION")
 		manifest, err := buildKustomizeManifest(kustomization)
 		Expect(err).NotTo(HaveOccurred())
 		err = clusterProxy.Apply(ctx, manifest)
 		Expect(err).NotTo(HaveOccurred())
 
-		bmoDeployment := &v1.Deployment{
+		ironicDeployment := &v1.Deployment{
 			ObjectMeta: metav1.ObjectMeta{
-				Name:      "baremetal-operator-controller-manager",
+				Name:      "baremetal-operator-ironic",
 				Namespace: "baremetal-operator-system",
 			},
 		}
 		// Wait for it to become available
 		framework.WaitForDeploymentsAvailable(ctx, framework.WaitForDeploymentsAvailableInput{
 			Getter:     clusterProxy.GetClient(),
-			Deployment: bmoDeployment,
-		}, e2eConfig.GetIntervals("default", "wait-deployment")...)
+			Deployment: ironicDeployment,
+		}, e2eConfig.GetIntervals("ironic", "wait-deployment")...)
 		// Set up log watcher
 		framework.WatchDeploymentLogsByName(ctx, framework.WatchDeploymentLogsByNameInput{
 			GetLister:  clusterProxy.GetClient(),
 			Cache:      clusterProxy.GetCache(ctx),
 			ClientSet:  clusterProxy.GetClientSet(),
-			Deployment: bmoDeployment,
-			LogPath:    filepath.Join(artifactFolder, "logs", bmoDeployment.GetNamespace()),
+			Deployment: ironicDeployment,
+			LogPath:    filepath.Join(artifactFolder, "logs", ironicDeployment.GetNamespace()),
 		})
 	}
 
diff --git a/test/e2e/external_inspection_test.go b/test/e2e/external_inspection_test.go
index 5de4f24b..49e33348 100644
--- a/test/e2e/external_inspection_test.go
+++ b/test/e2e/external_inspection_test.go
@@ -133,7 +133,7 @@ const hardwareDetails = `
       "version": "1.15.0-1"
     }
   },
-  "hostname": "bmo-e2e-0",
+  "hostname": "localhost.localdomain",
   "nics": [
     {
       "ip": "192.168.222.122",
diff --git a/test/e2e/live_iso_test.go b/test/e2e/live_iso_test.go
deleted file mode 100644
index 7a02e9ac..00000000
--- a/test/e2e/live_iso_test.go
+++ /dev/null
@@ -1,161 +0,0 @@
-package e2e
-
-import (
-	"context"
-	"fmt"
-
-	. "github.com/onsi/ginkgo/v2"
-	. "github.com/onsi/gomega"
-	"golang.org/x/crypto/ssh"
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/utils/pointer"
-	"sigs.k8s.io/cluster-api/test/framework"
-	"sigs.k8s.io/cluster-api/util"
-	"sigs.k8s.io/cluster-api/util/patch"
-
-	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
-
-	capm3_e2e "github.com/metal3-io/cluster-api-provider-metal3/test/e2e"
-)
-
-var _ = Describe("Live-ISO", func() {
-	var (
-		specName       = "live-iso-ops"
-		secretName     = "bmc-credentials"
-		namespace      *corev1.Namespace
-		cancelWatches  context.CancelFunc
-		bmcUser        string
-		bmcPassword    string
-		bmcAddress     string
-		bootMacAddress string
-		imageURL       string
-	)
-
-	BeforeEach(func() {
-		bmcUser = e2eConfig.GetVariable("BMC_USER")
-		bmcPassword = e2eConfig.GetVariable("BMC_PASSWORD")
-		bmcAddress = e2eConfig.GetVariable("BMC_ADDRESS")
-		bootMacAddress = e2eConfig.GetVariable("BOOT_MAC_ADDRESS")
-		imageURL = e2eConfig.GetVariable("IMAGE_URL")
-
-		namespace, cancelWatches = framework.CreateNamespaceAndWatchEvents(ctx, framework.CreateNamespaceAndWatchEventsInput{
-			Creator:   clusterProxy.GetClient(),
-			ClientSet: clusterProxy.GetClientSet(),
-			Name:      fmt.Sprintf("%s-%s", specName, util.RandomString(6)),
-			LogFolder: artifactFolder,
-		})
-	})
-
-	It("should provision a BMH with live ISO and then deprovision it", func() {
-		By("Creating a secret with BMH credentials")
-		CreateBMHCredentialsSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcUser, bmcPassword)
-
-		By("Creating a BMH with inspection disabled and hardware details added")
-		bmh := metal3api.BareMetalHost{
-			ObjectMeta: metav1.ObjectMeta{
-				Name:      specName,
-				Namespace: namespace.Name,
-				Annotations: map[string]string{
-					metal3api.InspectAnnotationPrefix:   "disabled",
-					metal3api.HardwareDetailsAnnotation: hardwareDetails,
-				},
-			},
-			Spec: metal3api.BareMetalHostSpec{
-				Online: true,
-				BMC: metal3api.BMCDetails{
-					Address:         bmcAddress,
-					CredentialsName: secretName,
-				},
-				Image: &metal3api.Image{
-					URL:        imageURL,
-					DiskFormat: pointer.String("live-iso"),
-				},
-				BootMode:              metal3api.Legacy,
-				BootMACAddress:        bootMacAddress,
-				AutomatedCleaningMode: "disabled",
-				RootDeviceHints: &metal3api.RootDeviceHints{
-					DeviceName: "/dev/vda",
-				},
-			},
-		}
-		err := clusterProxy.GetClient().Create(ctx, &bmh)
-		Expect(err).NotTo(HaveOccurred())
-
-		By("Waiting for the BMH to be in provisioning state")
-		WaitForBmhInProvisioningState(ctx, WaitForBmhInProvisioningStateInput{
-			Client: clusterProxy.GetClient(),
-			Bmh:    bmh,
-			State:  metal3api.StateProvisioning,
-		}, e2eConfig.GetIntervals(specName, "wait-provisioning")...)
-
-		By("Waiting for the BMH to become provisioned")
-		WaitForBmhInProvisioningState(ctx, WaitForBmhInProvisioningStateInput{
-			Client: clusterProxy.GetClient(),
-			Bmh:    bmh,
-			State:  metal3api.StateProvisioned,
-		}, e2eConfig.GetIntervals(specName, "wait-provisioned")...)
-
-		// The ssh check is not possible in all situations (e.g. fixture) so it can be skipped
-		if e2eConfig.GetVariable("SSH_CHECK_PROVISIONED") == "true" {
-			By("Verifying the node booted from live ISO image")
-
-			// Set up SSH client configuration
-			config := &ssh.ClientConfig{
-				User: "cirros",
-				Auth: []ssh.AuthMethod{
-					ssh.Password("gocubsgo"),
-				},
-				HostKeyCallback: ssh.InsecureIgnoreHostKey(), // #nosec G106
-			}
-
-			ip := e2eConfig.GetVariable("IP_BMO_E2E_0")
-			sshPort := e2eConfig.GetVariable("SSH_PORT")
-			address := fmt.Sprintf("%s:%s", ip, sshPort)
-
-			// Establish an SSH connection
-			var client *ssh.Client
-			var err error
-
-			Eventually(func() error {
-				client, err = ssh.Dial("tcp", address, config)
-				return err
-			}, e2eConfig.GetIntervals(specName, "wait-connect-ssh")...).Should(Succeed(), "Failed to establish SSH connection")
-
-			defer func() {
-				if client != nil {
-					client.Close()
-				}
-			}()
-			isDisk, err := IsBootedFromDisk(client)
-			Expect(err).NotTo(HaveOccurred(), "Error in verifying boot mode")
-			Expect(isDisk).To(Equal(false), "Error booting from disk when live ISO is expected")
-		} else {
-			capm3_e2e.Logf("WARNING: Skipping ssh check since SSH_CHECK_PROVISIONED != true")
-		}
-
-		By("Triggering the deprovisioning of the BMH")
-		helper, err := patch.NewHelper(&bmh, clusterProxy.GetClient())
-		Expect(err).NotTo(HaveOccurred())
-		bmh.Spec.Image = nil
-		Expect(helper.Patch(ctx, &bmh)).To(Succeed())
-
-		By("Waiting for the BMH to be in deprovisioning state")
-		WaitForBmhInProvisioningState(ctx, WaitForBmhInProvisioningStateInput{
-			Client: clusterProxy.GetClient(),
-			Bmh:    bmh,
-			State:  metal3api.StateDeprovisioning,
-		}, e2eConfig.GetIntervals(specName, "wait-deprovisioning")...)
-
-		By("Waiting for the BMH to become available again")
-		WaitForBmhInProvisioningState(ctx, WaitForBmhInProvisioningStateInput{
-			Client: clusterProxy.GetClient(),
-			Bmh:    bmh,
-			State:  metal3api.StateAvailable,
-		}, e2eConfig.GetIntervals(specName, "wait-available")...)
-	})
-
-	AfterEach(func() {
-		cleanup(ctx, clusterProxy, namespace, cancelWatches, e2eConfig.GetIntervals("default", "wait-namespace-deleted")...)
-	})
-})
diff --git a/test/e2e/re_inspection_test.go b/test/e2e/re_inspection_test.go
index d9b64986..93d947e7 100644
--- a/test/e2e/re_inspection_test.go
+++ b/test/e2e/re_inspection_test.go
@@ -54,7 +54,7 @@ var _ = Describe("Re-Inspection", func() {
 		CreateBMHCredentialsSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcUser, bmcPassword)
 
 		By("creating a BMH with inspection disabled and hardware details added with wrong HostName")
-		newHardwareDetails := strings.Replace(hardwareDetails, "bmo-e2e-0", wrongHostName, 1)
+		newHardwareDetails := strings.Replace(hardwareDetails, "localhost.localdomain", wrongHostName, 1)
 		bmh := metal3api.BareMetalHost{
 			ObjectMeta: metav1.ObjectMeta{
 				Name:      specName + "-reinspect",
diff --git a/test/go.mod b/test/go.mod
index 3249f27d..d27866e3 100644
--- a/test/go.mod
+++ b/test/go.mod
@@ -9,7 +9,6 @@ require (
 	github.com/onsi/ginkgo/v2 v2.13.0
 	github.com/onsi/gomega v1.29.0
 	github.com/pkg/errors v0.9.1
-	golang.org/x/crypto v0.14.0
 	gopkg.in/yaml.v2 v2.4.0
 	k8s.io/api v0.27.7
 	k8s.io/apimachinery v0.27.7
@@ -109,6 +108,7 @@ require (
 	github.com/valyala/fastjson v1.6.4 // indirect
 	github.com/xlab/treeprint v1.1.0 // indirect
 	go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
+	golang.org/x/crypto v0.14.0 // indirect
 	golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
 	golang.org/x/mod v0.12.0 // indirect
 	golang.org/x/net v0.17.0 // indirect