Repository: metal3-io/baremetal-operator
Pull request #2472 (2025-05-20 16:43:01)

⚠️ Prevent changing ExternallyProvisioned in the webhook
Changing ExternallyProvisioned does not actually work. Furthermore, it
results in a host hopelessly stuck in the "inspecting" state (in my
testing, I could not even delete it). Until we sort out this issue, let
us prevent users from getting into a problem.

Workaround for: #2465
Includes:
- https://github.com/metal3-io/baremetal-operator/pull/2471

Signed-off-by: Dmitry Tantsur <dtantsur@protonmail.com>


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 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: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/metal3-io/baremetal-operator/pull/2472#pullrequestreview-2856571062" title="Approved">lentzi90</a>*

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

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

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

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

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":[]} -->

Patch:
diff --git a/internal/webhooks/metal3.io/v1alpha1/baremetalhost_validation.go b/internal/webhooks/metal3.io/v1alpha1/baremetalhost_validation.go
index a3e2afe2..42317923 100644
--- a/internal/webhooks/metal3.io/v1alpha1/baremetalhost_validation.go
+++ b/internal/webhooks/metal3.io/v1alpha1/baremetalhost_validation.go
@@ -109,6 +109,10 @@ func (webhook *BareMetalHost) validateChanges(oldObj *metal3api.BareMetalHost, n
 		errs = append(errs, errors.New("bootMACAddress can not be changed once it is set"))
 	}
 
+	if oldObj.Spec.ExternallyProvisioned != newObj.Spec.ExternallyProvisioned {
+		errs = append(errs, errors.New("externallyProvisioned can not be changed"))
+	}
+
 	return errs
 }
 


Test patch:
diff --git a/internal/webhooks/metal3.io/v1alpha1/baremetalhost_validation_test.go b/internal/webhooks/metal3.io/v1alpha1/baremetalhost_validation_test.go
index 5d6ab808..609e15e5 100644
--- a/internal/webhooks/metal3.io/v1alpha1/baremetalhost_validation_test.go
+++ b/internal/webhooks/metal3.io/v1alpha1/baremetalhost_validation_test.go
@@ -76,6 +76,11 @@ func TestValidateCreate(t *testing.T) {
 			oldBMH:    nil,
 			wantedErr: "",
 		},
+		{
+			name:      "validExternallyProvisioned",
+			newBMH:    &metal3api.BareMetalHost{TypeMeta: tm, ObjectMeta: om, Spec: metal3api.BareMetalHostSpec{ExternallyProvisioned: true}},
+			wantedErr: "",
+		},
 		{
 			name:      "invalidName",
 			newBMH:    &metal3api.BareMetalHost{TypeMeta: tm, ObjectMeta: inom, Spec: metal3api.BareMetalHostSpec{}},
@@ -895,6 +900,14 @@ func TestValidateUpdate(t *testing.T) {
 				TypeMeta: tm, ObjectMeta: om, Spec: metal3api.BareMetalHostSpec{BootMACAddress: "test-mac"}},
 			wantedErr: "bootMACAddress can not be changed once it is set",
 		},
+		{
+			name: "updateExternallyProvisioned",
+			newBMH: &metal3api.BareMetalHost{
+				TypeMeta: tm, ObjectMeta: om, Spec: metal3api.BareMetalHostSpec{}},
+			oldBMH: &metal3api.BareMetalHost{
+				TypeMeta: tm, ObjectMeta: om, Spec: metal3api.BareMetalHostSpec{ExternallyProvisioned: true}},
+			wantedErr: "externallyProvisioned can not be changed",
+		},
 	}
 
 	for _, tt := range tests {