Skip to content

Conversation

@miyadav
Copy link
Member

@miyadav miyadav commented Oct 13, 2025

@sunzhaohua2 @huali9 PTAL when time permits , I have to omit few cases as error messages were not there for them , they actually get reconciled to old values , example labels of machinetype even after changing.

Also , my apologies the PR - #355 has been opened so long , even I forgot changes so , I took the rebase of latest code and recreated this one.

I will close that one.

Summary by CodeRabbit

  • Tests
    • Added end-to-end tests validating Verification and Access Policy (VAP) enforcement during Machine API migration on AWS.
    • Ensures updates to protected machine fields (providerID, taints, metadata) are blocked with clear VAP errors.
    • Prevents changes to AWS providerSpec fields (instance type, AMI, AZ, subnet, security groups, tags, capacity reservation).
    • Confirms VAP is bypassed when Machine API is authoritative.
    • Verifies protected label and annotation restrictions while allowing non-protected entries.
    • Includes setup/cleanup and reusable helpers for field-level verification.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Oct 13, 2025

📝 Walkthrough

Walkthrough

Adds a new AWS-focused Ginkgo end-to-end test file that implements Verification and Access Policy (VAP) enforcement scenarios for Machine API Migration (MAPI), including MAPI- and CAPI-enforcement suites, protected-field update checks, AWS providerSpec helpers, and a MachineAPI-authority bypass path. (≤50 words)

Changes

Cohort / File(s) Summary
E2E Tests for VAP Enforcement (AWS)
e2e/machine_migration_vap_tests.go
New Ginkgo E2E test file. Adds two gated suites (MAPI-driven VAP enforcement and CAPI enforcement). Tests cover spec/labels/annotations/providerSpec update restrictions, match-condition verification, and MachineAPI-authority bypass. Adds helper functions: verifyUpdatePrevented, verifyUpdateAllowed, verifyAWSProviderSpecUpdatePrevented, verifyVAPNotAppliedForMachineAPIAuthority, updateAWSMachineProviderSpec, getAWSProviderSpecFromMachine, verifyCAPIUpdatePrevented; includes setup/teardown and cleanup logic.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant T as Ginkgo Test
  participant K as Kubernetes API
  participant V as VAP Admission

  rect rgb(245,250,255)
    Note over T: Setup (AWS env, MAPI migration enabled)
    T->>K: Create MAPI Machine (authoritativeAPI=CAPI)
    K-->>T: Created
    T->>K: Create corresponding CAPI Machine
    K-->>T: Created
  end

  rect rgb(220,235,255)
    Note right of V: Enforcement when authoritativeAPI=CAPI
    T->>K: Patch protected fields (spec/labels/annotations/providerSpec)
    K->>V: AdmissionReview
    V-->>K: Deny with VAP error
    K-->>T: Update rejected (assert)
  end

  rect rgb(235,255,235)
    Note right of V: Bypass when authoritativeAPI=MachineAPI
    T->>K: Patch machine.authoritativeAPI -> MachineAPI
    K->>V: AdmissionReview
    V-->>K: Allow
    K-->>T: Update succeeds (assert)
  end

  Note over T: Cleanup and restore authoritativeAPI if changed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

I nibble at YAML with whiskers bright,
I hop through taints and labels in the night.
CAPI says "no" and the changes stall,
Flip to MachineAPI — the fences fall.
A rabbit cheers as tests dance light. 🐇

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title references a Jira ticket (OCPCLOUD-2566) and mentions 'tests with VAP msgs', which aligns with the changeset adding comprehensive VAP enforcement tests. However, it is vague and does not clearly convey the main focus (Machine API Migration VAP enforcement tests on AWS). Consider expanding the title to more clearly describe the purpose, such as 'OCPCLOUD-2566: Add Machine API Migration VAP enforcement tests' or similar, to make the primary change more evident to reviewers scanning the history.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (7)
e2e/machine_migration_vap_tests.go (7)

43-43: Avoid var _ = Describe inside a Describe; just call Describe/Context

Inside a Describe, prefer Describe(...) or Context(...) (no var _ =). This is cleaner and avoids confusing local var decls.

-	var _ = Describe("VAP: machine-api-machine-vap enforcement", Ordered, func() {
+	Describe("VAP: machine-api-machine-vap enforcement", Ordered, func() {

53-54: Make CAPI mirror retrieval resilient

GetMachine(...) may race the mirror creation. Wrap in Eventually (or a helper that waits) to avoid flaky NotFound.

Example:

-			testCAPIMachine = capiframework.GetMachine(cl, testMachineName, capiframework.CAPINamespace)
+			Eventually(func() (*clusterv1.Machine, error) {
+				m := capiframework.GetMachine(cl, testMachineName, capiframework.CAPINamespace)
+				if m == nil {
+					return nil, fmt.Errorf("CAPI machine not found yet")
+				}
+				return m, nil
+			}, capiframework.WaitMedium, capiframework.RetryMedium).Should(Not(BeNil()))
+			testCAPIMachine = capiframework.GetMachine(cl, testMachineName, capiframework.CAPINamespace)

Also confirm capiframework.GetMachine already waits; if so, this is unnecessary. Please verify.


55-63: Guard cleanup against nils

If mirror creation fails, testCAPIMachine can be nil. Ensure cleanupMachineResources tolerates nils or guard before passing.


239-256: Unused helpers; either exercise them or remove

verifyNonProtectedLabelUpdateAllowed and verifyNonProtectedAnnotationUpdateAllowed aren’t called. Keep tests lean: add small Its using them or drop to avoid dead code.

Also applies to: 297-314


279-295: Deletion test must ensure the annotation exists first

If the protected annotation isn’t present, deleting it is a no-op and may not trigger VAP. Seed it first, then attempt deletion in a separate update.

 func verifyProtectedAnnotationDeletionPrevented(machine *mapiv1beta1.Machine, annotationKey, expectedError string) {
   By(fmt.Sprintf("Verifying that deleting protected annotation %s is prevented by VAP", annotationKey))
 
+  // Ensure the annotation exists
+  Eventually(func() error {
+    if err := cl.Get(ctx, client.ObjectKeyFromObject(machine), machine); err != nil {
+      return err
+    }
+    if machine.Annotations == nil {
+      machine.Annotations = map[string]string{}
+    }
+    if _, ok := machine.Annotations[annotationKey]; !ok {
+      machine.Annotations[annotationKey] = "seed"
+    }
+    return cl.Update(ctx, machine)
+  }, capiframework.WaitMedium, capiframework.RetryMedium).Should(Succeed())
+
   Eventually(func() error {
     if err := cl.Get(ctx, client.ObjectKeyFromObject(machine), machine); err != nil {
       return err
     }
@@
   }, capiframework.WaitMedium, capiframework.RetryMedium).Should(
     MatchError(ContainSubstring(expectedError)),
     "Expected protected annotation deletion to be blocked by VAP")
 }

316-340: Add a test that VAP is not applied when authoritativeAPI=MachineAPI

You wrote verifyVAPNotAppliedForMachineAPIAuthority() but never call it. Add an It under its own Context to prevent regressions.

Example:

@@
-			Context("spec field restrictions", func() {
+			Context("spec field restrictions", func() {
@@
 			})
+			Context("when authoritativeAPI is MachineAPI", func() {
+				It("does not apply VAP to spec updates", func() {
+					verifyVAPNotAppliedForMachineAPIAuthority()
+				})
+			})

Also applies to: 66-86


25-30: Be cautious with exact error text assertions

Hard-coding full messages is brittle across policy/message tweaks. You already use ContainSubstring; consider matching a stable fragment (e.g., “modify spec.authoritativeAPI” / “authoritativeAPI is set to Cluster API”) or a regex to reduce churn.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 9704b30 and cb03d42.

📒 Files selected for processing (1)
  • e2e/machine_migration_vap_tests.go (1 hunks)
🔇 Additional comments (2)
e2e/machine_migration_vap_tests.go (2)

32-41: AWS + feature-gate guards look good

Platform guard and MachineAPIMigration gate are correct and reduce flakiness.


66-86: Spec-field restriction assertions are solid

ProviderID, taints, and spec.metadata checks are clear and use Eventually with substring match on VAP error. Nice.

Optional: After each denial, assert the field remains unchanged to prove no mutation leaked through.

Also applies to: 106-128, 130-171

@sunzhaohua2
Copy link
Contributor

Hi Milind, thanks for helping to check this. I found Theo has some comments in pr #355, can you help to take a look? especially use Komega instead of cl.Update, cl.Get. verifyAnnotationModificationPrevented becomes a more generic call to verifyUpdatePrevented

@miyadav
Copy link
Member Author

miyadav commented Oct 14, 2025

Just to add , sometimes , machine status is going to migrating and then the changes like annotations are not blocked , but reconciled so functionally it is working , but we won't get test for it to pass, as it is not getting the error message we expect.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between cb03d42 and 59c4dc8.

📒 Files selected for processing (1)
  • e2e/machine_migration_vap_tests.go (1 hunks)
🔇 Additional comments (2)
e2e/machine_migration_vap_tests.go (2)

220-248: LGTM! Good example of Komega usage.

This helper correctly uses komega.Update and komega.Object, demonstrating the pattern that should be followed in other helper functions.


345-363: LGTM! Correct Komega usage.

This helper correctly uses komega.Update and demonstrates proper cleanup with mapiframework.DeleteMachines.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
e2e/machine_migration_vap_tests.go (1)

169-200: Refactor helper to use Komega (per earlier feedback).

Prior review already asked for Komega over raw cl.Get/cl.Update. Please align verifyUpdatePrevented/verifyUpdateAllowed with the project pattern:

-func verifyUpdatePrevented(machine *mapiv1beta1.Machine, updateFunc func(*mapiv1beta1.Machine), expectedError string) {
+func verifyUpdatePrevented(machine *mapiv1beta1.Machine, updateFunc func(), expectedError string) {
@@
-	Eventually(func() error {
-		freshMachine := &mapiv1beta1.Machine{}
-		if err := cl.Get(ctx, client.ObjectKeyFromObject(machine), freshMachine); err != nil {
-			return err
-		}
-		updateFunc(freshMachine)
-		return cl.Update(ctx, freshMachine)
-	}, capiframework.WaitMedium, capiframework.RetryMedium).Should(
+	Eventually(komega.Update(machine, updateFunc), capiframework.WaitMedium, capiframework.RetryMedium).Should(

Apply the same pattern to verifyUpdateAllowed and update call sites to pass closures without the machine argument.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 59c4dc8 and 0e4e698.

📒 Files selected for processing (1)
  • e2e/machine_migration_vap_tests.go (1 hunks)

@miyadav miyadav marked this pull request as draft October 14, 2025 15:32
@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Oct 14, 2025
@miyadav miyadav force-pushed the 2566vaptests_latest branch from 918f2a5 to f57cd5c Compare October 15, 2025 12:19
@miyadav
Copy link
Member Author

miyadav commented Oct 15, 2025

/unhold

@miyadav miyadav marked this pull request as ready for review October 15, 2025 12:21
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Oct 15, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
e2e/machine_migration_vap_tests.go (3)

3-18: Stop using YAML for providerSpec; switch to encoding/json.

YAML bytes in runtime.RawExtension cause JSON encoding to fail before VAP, so tests won’t observe the policy error. Replace the YAML import with encoding/json.

 import (
+	"encoding/json"
 	"fmt"
 
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
@@
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/envtest/komega"
-	yaml "sigs.k8s.io/yaml"
 )

74-101: Missing coverage: spec.providerSpec update should be blocked

Add a test that mutates spec.providerSpec (e.g., instanceType) and asserts the VAP rejection.

 		Context("spec field restrictions", func() {
 			It("should prevent updating spec.providerID", func() {
@@
 			})
 
+			It("should prevent updating spec.providerSpec", func() {
+				verifyAWSProviderSpecUpdatePrevented(
+					testMAPIMachine,
+					"instanceType",
+					testInstanceType,
+					vapSpecLockedMessage,
+				)
+			})
 		})

183-255: providerSpec helper marshals with YAML; this breaks the update path

json is required for RawExtension. Swap yaml.Unmarshal/Marshal to encoding/json to let the Update reach VAP.

-	providerSpec := &mapiv1beta1.AWSMachineProviderConfig{}
-	if err := yaml.Unmarshal(freshMachine.Spec.ProviderSpec.Value.Raw, providerSpec); err != nil {
+	providerSpec := &mapiv1beta1.AWSMachineProviderConfig{}
+	if err := json.Unmarshal(freshMachine.Spec.ProviderSpec.Value.Raw, providerSpec); err != nil {
 		return fmt.Errorf("failed to unmarshal providerSpec: %v", err)
 	}
@@
-	// Marshal back to raw extension
-	modifiedRaw, err := yaml.Marshal(providerSpec)
+	// Marshal back to raw extension (JSON)
+	modifiedRaw, err := json.Marshal(providerSpec)
 	if err != nil {
 		return fmt.Errorf("failed to marshal modified providerSpec: %v", err)
 	}
 
 	freshMachine.Spec.ProviderSpec.Value = &runtime.RawExtension{Raw: modifiedRaw}
🧹 Nitpick comments (3)
e2e/machine_migration_vap_tests.go (3)

167-259: Prefer Komega here for consistency with other helpers

Use komega.Update instead of manual cl.Get/cl.Update for consistency and less boilerplate. Keep JSON marshal/unmarshal as above.

-func verifyAWSProviderSpecUpdatePrevented(machine *mapiv1beta1.Machine, fieldName string, testValue interface{}, expectedError string) {
-	By(fmt.Sprintf("Verifying that updating AWS providerSpec.%s is prevented by VAP", fieldName))
-
-	Eventually(func() error {
-		// Get fresh copy to avoid conflicts
-		freshMachine := &mapiv1beta1.Machine{}
-		if err := cl.Get(ctx, client.ObjectKeyFromObject(machine), freshMachine); err != nil {
-			return err
-		}
-		// Parse the current providerSpec
-		if freshMachine.Spec.ProviderSpec.Value == nil {
-			return fmt.Errorf("providerSpec is nil")
-		}
-		providerSpec := &mapiv1beta1.AWSMachineProviderConfig{}
-		if err := json.Unmarshal(freshMachine.Spec.ProviderSpec.Value.Raw, providerSpec); err != nil {
-			return fmt.Errorf("failed to unmarshal providerSpec: %v", err)
-		}
-		// ... mutate switch ...
-		modifiedRaw, err := json.Marshal(providerSpec)
-		if err != nil {
-			return fmt.Errorf("failed to marshal modified providerSpec: %v", err)
-		}
-		freshMachine.Spec.ProviderSpec.Value = &runtime.RawExtension{Raw: modifiedRaw}
-		return cl.Update(ctx, freshMachine)
-	}, capiframework.WaitMedium, capiframework.RetryMedium).Should(
-		MatchError(ContainSubstring(expectedError)),
-		"Expected AWS providerSpec.%s update to be blocked by VAP", fieldName)
-}
+func verifyAWSProviderSpecUpdatePrevented(machine *mapiv1beta1.Machine, fieldName string, testValue interface{}, expectedError string) {
+	By(fmt.Sprintf("Verifying that updating AWS providerSpec.%s is prevented by VAP", fieldName))
+	Eventually(komega.Update(machine, func() {
+		if machine.Spec.ProviderSpec.Value == nil || len(machine.Spec.ProviderSpec.Value.Raw) == 0 {
+			return
+		}
+		providerSpec := &mapiv1beta1.AWSMachineProviderConfig{}
+		if err := json.Unmarshal(machine.Spec.ProviderSpec.Value.Raw, providerSpec); err != nil {
+			return
+		}
+		switch fieldName {
+		case "instanceType":
+			providerSpec.InstanceType = testValue.(string)
+		case "amiID":
+			s := testValue.(string)
+			if providerSpec.AMI.ID == nil {
+				providerSpec.AMI.ID = &s
+			} else {
+				*providerSpec.AMI.ID = s
+			}
+		case "availabilityZone":
+			providerSpec.Placement.AvailabilityZone = testValue.(string)
+		case "subnetID":
+			s := testValue.(string)
+			providerSpec.Subnet = mapiv1beta1.AWSResourceReference{ID: &s}
+		case "securityGroups":
+			s := testValue.(string)
+			providerSpec.SecurityGroups = []mapiv1beta1.AWSResourceReference{{ID: &s}}
+		case "volumeSize":
+			if len(providerSpec.BlockDevices) > 0 && providerSpec.BlockDevices[0].EBS != nil {
+				v := testValue.(int64)
+				providerSpec.BlockDevices[0].EBS.VolumeSize = &v
+			}
+		case "volumeType":
+			if len(providerSpec.BlockDevices) > 0 && providerSpec.BlockDevices[0].EBS != nil {
+				s := testValue.(string)
+				providerSpec.BlockDevices[0].EBS.VolumeType = &s
+			}
+		case "encryption":
+			if len(providerSpec.BlockDevices) > 0 && providerSpec.BlockDevices[0].EBS != nil {
+				b := testValue.(bool)
+				providerSpec.BlockDevices[0].EBS.Encrypted = &b
+			}
+		case "tags":
+			tagMap := testValue.(map[string]string)
+			var tags []mapiv1beta1.TagSpecification
+			for k, v := range tagMap {
+				tags = append(tags, mapiv1beta1.TagSpecification{Name: k, Value: v})
+			}
+			providerSpec.Tags = tags
+		default:
+			return
+		}
+		if raw, err := json.Marshal(providerSpec); err == nil {
+			machine.Spec.ProviderSpec.Value.Raw = raw
+		}
+	}), capiframework.WaitMedium, capiframework.RetryMedium).Should(
+		MatchError(ContainSubstring(expectedError)),
+		fmt.Sprintf("Expected AWS providerSpec.%s update to be blocked by VAP", fieldName),
+	)
+}

26-33: Unused providerSpec test constants

These constants are currently unused. Either use them in providerSpec tests or remove to reduce noise.


102-120: Optional: also assert kubernetes.io/ label protection*

You only test machine.openshift.io/; consider adding a kubernetes.io/ case for completeness.

It("should prevent modifying kubernetes.io/* labels", func() {
	verifyUpdatePrevented(testMAPIMachine, func() {
		if testMAPIMachine.Labels == nil {
			testMAPIMachine.Labels = make(map[string]string)
		}
		testMAPIMachine.Labels["kubernetes.io/test-label"] = testLabelValue
	}, vapProtectedLabelMessage)
})
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 0e4e698 and f57cd5c.

📒 Files selected for processing (1)
  • e2e/machine_migration_vap_tests.go (1 hunks)
🔇 Additional comments (1)
e2e/machine_migration_vap_tests.go (1)

150-165: Good use of Komega wrappers

verifyUpdatePrevented/Allowed follow the recommended Komega pattern.

@chrischdi
Copy link
Contributor

@miyadav can we have a proper title for the PR? (including OCPCLOUD-<id>: <title>

@miyadav miyadav changed the title OCPCLOUD-2566 -tests with VAP msgs OCPCLOUD-2566: tests with VAP msgs Oct 15, 2025
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Oct 15, 2025
@openshift-ci-robot
Copy link

openshift-ci-robot commented Oct 15, 2025

@miyadav: This pull request references OCPCLOUD-2566 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target either version "4.21." or "openshift-4.21.", but it targets "openshift-4.20" instead.

Details

In response to this:

@sunzhaohua2 @huali9 PTAL when time permits , I have to omit few cases as error messages were not there for them , they actually get reconciled to old values , example labels of machinetype even after changing.

Also , my apologies the PR - #355 has been opened so long , even I forgot changes so , I took the rebase of latest code and recreated this one.

I will close that one.

Summary by CodeRabbit

  • Tests
  • Added comprehensive end-to-end tests for Machine API migration VAP enforcement on AWS.
  • Verifies protected machine fields (providerID, taints, providerSpec, metadata) are blocked with specific VAP errors.
  • Confirms updates to authoritativeAPI are allowed and VAP is not enforced when MachineAPI is authoritative.
  • Validates protected label and annotation restrictions while allowing non-protected exceptions.
  • Includes setup, cleanup, and reusable helpers to ensure reliable, field-level enforcement checks.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot
Copy link

openshift-ci-robot commented Oct 21, 2025

@miyadav: This pull request references OCPCLOUD-2566 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target either version "4.21." or "openshift-4.21.", but it targets "openshift-4.20" instead.

Details

In response to this:

@sunzhaohua2 @huali9 PTAL when time permits , I have to omit few cases as error messages were not there for them , they actually get reconciled to old values , example labels of machinetype even after changing.

Also , my apologies the PR - #355 has been opened so long , even I forgot changes so , I took the rebase of latest code and recreated this one.

I will close that one.

Summary by CodeRabbit

  • Tests
  • Added end-to-end tests validating VAP enforcement during Machine API migration on AWS.
  • Ensures updates to protected machine fields (providerID, taints, providerSpec, metadata) are blocked with explicit VAP errors.
  • Confirms VAP is not enforced when MachineAPI is the authoritative API.
  • Verifies protected label and annotation restrictions while allowing non-protected entries.
  • Includes setup, cleanup, and reusable helpers for reliable, field-level verification.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
e2e/machine_migration_vap_tests.go (5)

74-100: Add a providerSpec update test to fully exercise spec lock.

spec.providerSpec changes are part of VAP enforcement but are not covered here. You already have constants and a helper for this. Add a focused test to prevent regressions.

Apply near this context:

 Context("spec field restrictions", func() {
   It("should prevent updating spec.providerID", func() {
     verifyUpdatePrevented(testMAPIMachine, func() {
       providerIDValue := testProviderID
       testMAPIMachine.Spec.ProviderID = &providerIDValue
     }, vapSpecLockedMessage)
   })

+  It("should prevent updating spec.providerSpec (e.g., instanceType)", func() {
+    // Reuses the existing helper and constants
+    verifyAWSProviderSpecUpdatePrevented(testMAPIMachine, "instanceType", testInstanceType, vapSpecLockedMessage)
+  })
 })

56-72: Optional: wait for status.authoritativeAPI=ClusterAPI to reduce flakes.

Enforcement depends on status.authoritativeAPI. A short readiness wait here can make CI steadier without changing behavior.

 BeforeAll(func() {
   // Create a MAPI machine with ClusterAPI authority to trigger VAP enforcement
   testMAPIMachine = createMAPIMachineWithAuthority(ctx, cl, testMachineName, mapiv1beta1.MachineAuthorityClusterAPI)

   // The VAP requires a matching CAPI machine as parameter
   testCAPIMachine = capiframework.GetMachine(cl, testMachineName, capiframework.CAPINamespace)

+  // Harden: wait until enforcement condition is actually met
+  Eventually(func() (mapiv1beta1.MachineAuthority, error) {
+    fresh := &mapiv1beta1.Machine{}
+    err := cl.Get(ctx, client.ObjectKeyFromObject(testMAPIMachine), fresh)
+    return fresh.Status.AuthoritativeAPI, err
+  }, capiframework.WaitLong, capiframework.RetryMedium).Should(
+    Equal(mapiv1beta1.MachineAuthorityClusterAPI),
+    "expect status.authoritativeAPI=ClusterAPI before enforcement checks",
+  )

167-259: ProviderSpec helper: avoid silent no-ops and align with Komega.

  • Today, several cases can end up not modifying anything (e.g., missing BlockDevices/EBS) yet proceed to Update, risking misleading outcomes if used later.
  • Style: the rest of the file uses komega.Update; consider the same for consistency.

Minimal robustness tweak (keep cl.Get/Update) — ensure a real mutation or fail fast:

 func verifyAWSProviderSpecUpdatePrevented(machine *mapiv1beta1.Machine, fieldName string, testValue interface{}, expectedError string) {
   By(fmt.Sprintf("Verifying that updating AWS providerSpec.%s is prevented by VAP", fieldName))

   Eventually(func() error {
@@
-    // Modify the specified field
+    // Modify the specified field
+    modified := false
     switch fieldName {
     case "instanceType":
       providerSpec.InstanceType = testValue.(string)
+      modified = true
     case "amiID":
       testValueStr := testValue.(string)
       if providerSpec.AMI.ID == nil {
         providerSpec.AMI.ID = &testValueStr
       } else {
         *providerSpec.AMI.ID = testValueStr
       }
+      modified = true
     case "availabilityZone":
       providerSpec.Placement.AvailabilityZone = testValue.(string)
+      modified = true
     case "subnetID":
       testValueStr := testValue.(string)
       providerSpec.Subnet = mapiv1beta1.AWSResourceReference{
         ID: &testValueStr,
       }
+      modified = true
     case "securityGroups":
       providerSpec.SecurityGroups = []mapiv1beta1.AWSResourceReference{{
         ID: &[]string{testValue.(string)}[0],
       }}
+      modified = true
     case "volumeSize":
       if len(providerSpec.BlockDevices) > 0 && providerSpec.BlockDevices[0].EBS != nil {
         providerSpec.BlockDevices[0].EBS.VolumeSize = &[]int64{testValue.(int64)}[0]
+        modified = true
       }
     case "volumeType":
       if len(providerSpec.BlockDevices) > 0 && providerSpec.BlockDevices[0].EBS != nil {
         providerSpec.BlockDevices[0].EBS.VolumeType = &[]string{testValue.(string)}[0]
+        modified = true
       }
     case "encryption":
       if len(providerSpec.BlockDevices) > 0 && providerSpec.BlockDevices[0].EBS != nil {
         providerSpec.BlockDevices[0].EBS.Encrypted = &[]bool{testValue.(bool)}[0]
+        modified = true
       }
     case "tags":
@@
       providerSpec.Tags = tags
+      modified = true
-    case "capacityReservationId":
-      providerSpec.SpotMarketOptions = &mapiv1beta1.SpotMarketOptions{
-        MaxPrice: &[]string{"0.10"}[0],
-      }
-      // Note: capacityReservationId might be in different location based on AWS API version
     default:
       return fmt.Errorf("unsupported field: %s", fieldName)
     }
+
+    if !modified {
+      return fmt.Errorf("no-op mutation for field %q (missing nested fields?)", fieldName)
+    }

If you prefer full consistency, I can also rewrite this helper to use komega.Update and return a komega closure while still surfacing parse/mutation errors. Want me to push that version?


20-38: Prune or use the extra providerSpec constants.

testInstanceType, testAMIID, testAvailabilityZone, testSubnetID, testSecurityGroupID, testVolumeSize, and testCapacityReservationID are currently unused in tests. Either use them (e.g., in the providerSpec test) or remove to keep the file lean.


261-280: Optional: avoid name collisions for the MachineAPI-authority test.

To be safer under parallel CI or repeated runs, add a unique suffix.

- testMachine := createMAPIMachineWithAuthority(ctx, cl, "vap-test-mapi-authority", mapiv1beta1.MachineAuthorityMachineAPI)
+ uniqueName := fmt.Sprintf("vap-test-mapi-authority-%d", GinkgoParallelProcess())
+ testMachine := createMAPIMachineWithAuthority(ctx, cl, uniqueName, mapiv1beta1.MachineAuthorityMachineAPI)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between f57cd5c and daaff8d.

📒 Files selected for processing (1)
  • e2e/machine_migration_vap_tests.go (1 hunks)
🔇 Additional comments (3)
e2e/machine_migration_vap_tests.go (3)

102-120: Protected labels: good coverage.

Blocking machine.openshift.io/* while allowing non-protected labels is clearly tested.


122-140: Protected annotations: good coverage.

Denial for machine.openshift.io/* and allow-list for others looks correct.


150-165: Komega-based update helpers look solid.

Nice switch to komega.Update with bounded waits/retries; assertions read well.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
e2e/machine_migration_vap_tests.go (2)

26-33: Build blocker: unused constants cause compile failure

These constants are never referenced, so go test will fail with “declared and not used”. Either use them in tests or remove them.

Apply this minimal fix (keep only those actually used today and the one we’ll use in the providerSpec test below):

 const (
   // Test values for MAPI machine updates
   testProviderID            = "aws:///us-west-2a/i-test123456"
   testTaintValue            = "test-taint-value"
   testLabelValue            = "test-label-value"
   testInstanceType          = "m5.xlarge"
-  testAMIID                 = "ami-test123456"
-  testAvailabilityZone      = "us-west-2b"
-  testSubnetID              = "subnet-test123456"
-  testSecurityGroupID       = "sg-test123456"
-  testVolumeSize            = int64(120)
-  testCapacityReservationID = "cr-test123456"

74-100: Missing providerSpec coverage — add a focused test

VAP should block providerSpec edits, but there’s no test exercising it. Use the existing helper.

   Context("spec field restrictions", func() {
@@
     It("should prevent updating spec.metadata", func() {
       verifyUpdatePrevented(testMAPIMachine, func() {
         if testMAPIMachine.Spec.ObjectMeta.Labels == nil {
           testMAPIMachine.Spec.ObjectMeta.Labels = make(map[string]string)
         }
         testMAPIMachine.Spec.ObjectMeta.Labels["test-spec-label"] = testLabelValue
       }, vapSpecLockedMessage)
     })
+
+    It("should prevent updating spec.providerSpec (instanceType)", func() {
+      verifyAWSProviderSpecUpdatePrevented(
+        testMAPIMachine,
+        "instanceType",
+        testInstanceType,
+        vapSpecLockedMessage,
+      )
+    })
   })
🧹 Nitpick comments (5)
e2e/machine_migration_vap_tests.go (5)

171-176: Use Komega here for consistency with the rest of the suite

This helper still uses raw client Get/Update. Prefer Komega like your other helpers.

 func verifyAWSProviderSpecUpdatePrevented(machine *mapiv1beta1.Machine, fieldName string, testValue interface{}, expectedError string) {
   By(fmt.Sprintf("Verifying that updating AWS providerSpec.%s is prevented by VAP", fieldName))
-
-  Eventually(func() error {
-    // Get fresh copy to avoid conflicts
-    freshMachine := &mapiv1beta1.Machine{}
-    if err := cl.Get(ctx, client.ObjectKeyFromObject(machine), freshMachine); err != nil {
-      return err
-    }
+  Eventually(komega.Update(machine, func() {
+    freshMachine := machine
@@
-    freshMachine.Spec.ProviderSpec.Value = &runtime.RawExtension{Raw: modifiedRaw}
-    return cl.Update(ctx, freshMachine)
-  }, capiframework.WaitMedium, capiframework.RetryMedium).Should(
+    freshMachine.Spec.ProviderSpec.Value = &runtime.RawExtension{Raw: modifiedRaw}
+  }), capiframework.WaitMedium, capiframework.RetryMedium).Should(
     MatchError(ContainSubstring(expectedError)),
     "Expected AWS providerSpec.%s update to be blocked by VAP", fieldName)
 }

Also remove the now-unused import "sigs.k8s.io/controller-runtime/pkg/client".

Also applies to: 251-253


211-227: Guard against no-op when BlockDevices/EBS is empty

If BlockDevices is empty or EBS is nil, the mutation won’t change anything, risking false negatives.

-    case "volumeSize":
-      if len(providerSpec.BlockDevices) > 0 {
-        if providerSpec.BlockDevices[0].EBS != nil {
-          providerSpec.BlockDevices[0].EBS.VolumeSize = &[]int64{testValue.(int64)}[0]
-        }
-      }
+    case "volumeSize":
+      if len(providerSpec.BlockDevices) == 0 {
+        providerSpec.BlockDevices = []mapiv1beta1.BlockDeviceMappingSpec{{EBS: &mapiv1beta1.EBSBlockDeviceSpec{}}}
+      } else if providerSpec.BlockDevices[0].EBS == nil {
+        providerSpec.BlockDevices[0].EBS = &mapiv1beta1.EBSBlockDeviceSpec{}
+      }
+      providerSpec.BlockDevices[0].EBS.VolumeSize = &[]int64{testValue.(int64)}[0]
@@
-    case "volumeType":
-      if len(providerSpec.BlockDevices) > 0 {
-        if providerSpec.BlockDevices[0].EBS != nil {
-          providerSpec.BlockDevices[0].EBS.VolumeType = &[]string{testValue.(string)}[0]
-        }
-      }
+    case "volumeType":
+      if len(providerSpec.BlockDevices) == 0 {
+        providerSpec.BlockDevices = []mapiv1beta1.BlockDeviceMappingSpec{{EBS: &mapiv1beta1.EBSBlockDeviceSpec{}}}
+      } else if providerSpec.BlockDevices[0].EBS == nil {
+        providerSpec.BlockDevices[0].EBS = &mapiv1beta1.EBSBlockDeviceSpec{}
+      }
+      providerSpec.BlockDevices[0].EBS.VolumeType = &[]string{testValue.(string)}[0]
@@
-    case "encryption":
-      if len(providerSpec.BlockDevices) > 0 {
-        if providerSpec.BlockDevices[0].EBS != nil {
-          providerSpec.BlockDevices[0].EBS.Encrypted = &[]bool{testValue.(bool)}[0]
-        }
-      }
+    case "encryption":
+      if len(providerSpec.BlockDevices) == 0 {
+        providerSpec.BlockDevices = []mapiv1beta1.BlockDeviceMappingSpec{{EBS: &mapiv1beta1.EBSBlockDeviceSpec{}}}
+      } else if providerSpec.BlockDevices[0].EBS == nil {
+        providerSpec.BlockDevices[0].EBS = &mapiv1beta1.EBSBlockDeviceSpec{}
+      }
+      providerSpec.BlockDevices[0].EBS.Encrypted = &[]bool{testValue.(bool)}[0]

102-120: Add coverage for kubernetes.io/ protected labels*

Your message asserts both machine.openshift.io/* and kubernetes.io/* are protected; only the former is tested.

   Context("protected label restrictions", func() {
@@
     It("should allow modifying non-protected labels", func() {
       verifyUpdateAllowed(testMAPIMachine, func() {
         if testMAPIMachine.Labels == nil {
           testMAPIMachine.Labels = make(map[string]string)
         }
         testMAPIMachine.Labels["test-label"] = "allowed-value"
       })
     })
+
+    It("should prevent modifying kubernetes.io/* labels", func() {
+      verifyUpdatePrevented(testMAPIMachine, func() {
+        if testMAPIMachine.Labels == nil {
+          testMAPIMachine.Labels = make(map[string]string)
+        }
+        testMAPIMachine.Labels["kubernetes.io/test-label"] = testLabelValue
+      }, vapProtectedLabelMessage)
+    })
   })

207-209: Minor: avoid ephemeral pointer trick for strings

Prefer a helper for clarity, e.g., k8s.io/utils/ptr.

-      providerSpec.SecurityGroups = []mapiv1beta1.AWSResourceReference{{
-        ID: &[]string{testValue.(string)}[0],
-      }}
+      sg := testValue.(string)
+      providerSpec.SecurityGroups = []mapiv1beta1.AWSResourceReference{{ID: &sg}}

56-72: Optional: wait for authoritativeAPI readiness to de-flake

If you hit flakes, explicitly wait until status.authoritativeAPI == ClusterAPI before assertions.

   BeforeAll(func() {
@@
     testCAPIMachine = capiframework.GetMachine(cl, testMachineName, capiframework.CAPINamespace)
+
+    Eventually(func() (mapiv1beta1.MachineAuthority, error) {
+      fresh := &mapiv1beta1.Machine{}
+      err := cl.Get(ctx, client.ObjectKeyFromObject(testMAPIMachine), fresh)
+      return fresh.Status.AuthoritativeAPI, err
+    }, capiframework.WaitLong, capiframework.RetryMedium).Should(
+      Equal(mapiv1beta1.MachineAuthorityClusterAPI),
+      "VAP enforces only after status.authoritativeAPI=ClusterAPI",
+    )
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between daaff8d and c4750a1.

📒 Files selected for processing (1)
  • e2e/machine_migration_vap_tests.go (1 hunks)
🔇 Additional comments (1)
e2e/machine_migration_vap_tests.go (1)

239-241: capacityReservationId mutation looks correct now

This fixes the earlier mismatch (was mutating Spot options). No further action.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
e2e/machine_migration_vap_tests.go (1)

238-241: Simplify the pointer creation for SecurityGroups ID.

The pattern &[]string{testValue.(string)}[0] creates a slice just to take a pointer to its first element, which is unnecessarily complex and harder to read.

Apply this diff to improve clarity:

 	case "securityGroups":
+		id := testValue.(string)
 		providerSpec.SecurityGroups = []mapiv1beta1.AWSResourceReference{{
-			ID: &[]string{testValue.(string)}[0],
+			ID: &id,
 		}}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between c4750a1 and 3f188cb.

📒 Files selected for processing (1)
  • e2e/machine_migration_vap_tests.go (1 hunks)

@miyadav
Copy link
Member Author

miyadav commented Oct 23, 2025

/test okd-scos-e2e-aws-ovn

1 similar comment
@miyadav
Copy link
Member Author

miyadav commented Oct 23, 2025

/test okd-scos-e2e-aws-ovn

return fmt.Errorf("providerSpec is nil")
}

providerSpec := &mapiv1beta1.AWSMachineProviderConfig{}
Copy link
Contributor

@theobarberbany theobarberbany Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have a helperfunc elsewhere that does something very similar to this? I think we added one in one of the other PRs?

(specifically one with an updateFunc() being passed in pattern)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remember now did it in pr 355. Will update

@miyadav miyadav force-pushed the 2566vaptests_latest branch from 3f188cb to b01f005 Compare October 23, 2025 14:51
@openshift-ci-robot
Copy link

openshift-ci-robot commented Oct 23, 2025

@miyadav: This pull request references OCPCLOUD-2566 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target either version "4.21." or "openshift-4.21.", but it targets "openshift-4.20" instead.

Details

In response to this:

@sunzhaohua2 @huali9 PTAL when time permits , I have to omit few cases as error messages were not there for them , they actually get reconciled to old values , example labels of machinetype even after changing.

Also , my apologies the PR - #355 has been opened so long , even I forgot changes so , I took the rebase of latest code and recreated this one.

I will close that one.

Summary by CodeRabbit

  • Tests
  • Added end-to-end tests validating VAP enforcement during Machine API migration on AWS.
  • Ensures updates to protected machine fields (providerID, taints, metadata, providerSpec fields like instance type, AMI, AZ, subnet, security groups, tags) are blocked with explicit VAP errors.
  • Confirms VAP is not enforced when Machine API is authoritative.
  • Verifies protected label and annotation restrictions while allowing non-protected entries.
  • Includes setup, cleanup, and reusable helpers for field-level verification.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Dec 4, 2025
@miyadav
Copy link
Member Author

miyadav commented Jan 7, 2026

/retest-required

@damdo
Copy link
Member

damdo commented Jan 7, 2026

/unhold

@openshift-ci openshift-ci bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jan 7, 2026
@miyadav
Copy link
Member Author

miyadav commented Jan 7, 2026

@damdo @theobarberbany I will rebase this and add a small test scenario to it , seems like the unit test was updated in master , this branch(my PR) doesn't have it. Also some imports changed ( clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" to "clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2") , hence it is failing.

removing the part which is covered in other PRs
co-author: cursor & coderabbitAI
reduce time,changes to follow consistent pattern
@openshift-ci-robot
Copy link

/retest-required

Remaining retests: 0 against base HEAD 2fe5bfa and 2 for PR HEAD ebde40b in total

@miyadav miyadav force-pushed the 2566vaptests_latest branch from ebde40b to 8b854d4 Compare January 7, 2026 11:39
@openshift-ci-robot openshift-ci-robot removed the verified Signifies that the PR passed pre-merge verification criteria label Jan 7, 2026
@openshift-ci openshift-ci bot removed the lgtm Indicates that a PR is ready to be merged. label Jan 7, 2026
@openshift-ci-robot
Copy link

openshift-ci-robot commented Jan 7, 2026

@miyadav: This pull request references OCPCLOUD-2566 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target either version "4.22." or "openshift-4.22.", but it targets "openshift-4.20" instead.

Details

In response to this:

@sunzhaohua2 @huali9 PTAL when time permits , I have to omit few cases as error messages were not there for them , they actually get reconciled to old values , example labels of machinetype even after changing.

Also , my apologies the PR - #355 has been opened so long , even I forgot changes so , I took the rebase of latest code and recreated this one.

I will close that one.

Summary by CodeRabbit

  • Tests
  • Added end-to-end tests validating Verification and Access Policy (VAP) enforcement during Machine API migration on AWS.
  • Ensures updates to protected machine fields (providerID, taints, metadata) are blocked with clear VAP errors.
  • Prevents changes to AWS providerSpec fields (instance type, AMI, AZ, subnet, security groups, tags, capacity reservation).
  • Confirms VAP is bypassed when Machine API is authoritative.
  • Verifies protected label and annotation restrictions while allowing non-protected entries.
  • Includes setup/cleanup and reusable helpers for field-level verification.

✏️ Tip: You can customize this high-level summary in your review settings.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
e2e/machine_migration_vap_tests.go (1)

52-56: Consider removing var _ = from nested Describe blocks.

The var _ = Describe(...) pattern is typically used at the top level to ensure test registration during init. Inside a parent Describe block, the nested Describe is just a function call, so var _ = is unnecessary.

♻️ Suggested simplification
-	var _ = Describe("VAP: machine-api-machine-vap enforcement", Ordered, func() {
+	Describe("VAP: machine-api-machine-vap enforcement", Ordered, func() {

Same applies to line 216.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between ebde40b and 8b854d4.

📒 Files selected for processing (1)
  • e2e/machine_migration_vap_tests.go
🧰 Additional context used
🧬 Code graph analysis (1)
e2e/machine_migration_vap_tests.go (4)
e2e/framework/util.go (1)
  • IsMachineAPIMigrationEnabled (41-76)
pkg/conversion/mapi2capi/interface.go (1)
  • Machine (24-26)
e2e/framework/machine.go (2)
  • GetMachine (75-86)
  • DeleteMachines (105-135)
e2e/framework/framework.go (3)
  • CAPINamespace (14-14)
  • WaitMedium (24-24)
  • RetryMedium (18-18)
🔇 Additional comments (11)
e2e/machine_migration_vap_tests.go (11)

3-39: LGTM - Imports and constants are well-organized.

The use of encoding/json for providerSpec marshaling is correct (addresses previous YAML-related concerns). Constants are appropriately defined for VAP error messages and test values.


41-51: LGTM - Proper test gating.

The platform and feature gate checks appropriately skip tests on non-AWS platforms and clusters without MachineAPIMigration enabled.


57-81: LGTM - Proper test setup with status synchronization.

The wait for status.authoritativeAPI before running VAP enforcement tests ensures the VAP match conditions are met, preventing flakiness. Cleanup is properly registered with DeferCleanup.


83-109: LGTM - Spec field restriction tests are comprehensive.

Tests appropriately verify that spec.providerID, spec.taints, and spec.metadata updates are blocked by VAP when authoritativeAPI is ClusterAPI.


111-149: LGTM - Label and annotation restriction tests provide good coverage.

Tests appropriately verify that machine.openshift.io/* labels and annotations are blocked while non-protected labels and annotations are allowed.


151-207: LGTM - AWS providerSpec field restriction tests are thorough.

Tests cover key AWS-specific fields including instanceType, AMI, availability zone, subnet, security groups, tags, and capacity reservation. The capacityReservationId test now correctly modifies providerSpec.CapacityReservationID.


216-268: LGTM - CAPI Machine VAP enforcement tests are well-structured.

Tests appropriately verify that forbidden CAPI fields (spec.version and spec.readinessGates) are blocked by the CAPI VAP. The readinessGates test correctly handles both modification and addition scenarios.


271-295: LGTM - Helper functions use Komega correctly.

The verifyUpdatePrevented, verifyUpdateAllowed, and verifyCAPIUpdatePrevented helpers appropriately use komega.Update with the closure pattern, addressing previous review feedback.


297-321: LGTM - AWS providerSpec helpers use JSON correctly.

The use of encoding/json for marshaling/unmarshaling the providerSpec addresses the previous YAML-related issue. The getAWSProviderSpecFromMachine helper appropriately uses Gomega assertions for validation.


323-332: LGTM - AWS providerSpec update verification helper is well-designed.

The nested Expect(updateAWSMachineProviderSpec(...)) inside the komega.Update closure correctly propagates any marshaling failures to the Eventually assertion.


334-361: LGTM - VAP bypass verification is correctly implemented.

The function appropriately waits for status.authoritativeAPI=MachineAPI before testing, addressing previous flakiness concerns. The use of mapiframework.DeleteMachines instead of cleanupMachineResources is correct here since no corresponding CAPI machine is created when authority is MachineAPI.

@miyadav
Copy link
Member Author

miyadav commented Jan 7, 2026

/retest

@damdo
Copy link
Member

damdo commented Jan 7, 2026

/test ci/prow/okd-scos-images

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jan 7, 2026

@damdo: The specified target(s) for /test were not found.
The following commands are available to trigger required jobs:

/test build
/test e2e-aws-capi-techpreview
/test e2e-aws-ovn
/test e2e-aws-ovn-serial-1of2
/test e2e-aws-ovn-serial-2of2
/test e2e-aws-ovn-techpreview
/test e2e-aws-ovn-techpreview-upgrade
/test e2e-azure-capi-techpreview
/test e2e-azure-ovn-techpreview-upgrade
/test e2e-gcp-capi-techpreview
/test e2e-gcp-ovn-techpreview
/test e2e-openstack-capi-techpreview
/test e2e-openstack-ovn-techpreview
/test e2e-vsphere-capi-techpreview
/test images
/test lint
/test okd-scos-images
/test unit
/test vendor
/test verify-deps

The following commands are available to trigger optional jobs:

/test e2e-azure-ovn-techpreview
/test e2e-metal3-capi-techpreview
/test okd-scos-e2e-aws-ovn
/test regression-clusterinfra-aws-ipi-techpreview-capi

Use /test all to run the following jobs that were automatically triggered:

pull-ci-openshift-cluster-capi-operator-main-build
pull-ci-openshift-cluster-capi-operator-main-images
pull-ci-openshift-cluster-capi-operator-main-lint
pull-ci-openshift-cluster-capi-operator-main-okd-scos-images
pull-ci-openshift-cluster-capi-operator-main-unit
pull-ci-openshift-cluster-capi-operator-main-vendor
pull-ci-openshift-cluster-capi-operator-main-verify-deps
Details

In response to this:

/test ci/prow/okd-scos-images

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@damdo
Copy link
Member

damdo commented Jan 7, 2026

/override ci/prow/okd-scos-images

@damdo
Copy link
Member

damdo commented Jan 7, 2026

/verified by e2es in CI

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jan 7, 2026

@damdo: Overrode contexts on behalf of damdo: ci/prow/okd-scos-images

Details

In response to this:

/override ci/prow/okd-scos-images

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label Jan 7, 2026
@openshift-ci-robot
Copy link

@damdo: This PR has been marked as verified by e2es in CI.

Details

In response to this:

/verified by e2es in CI

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link
Member

@damdo damdo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readding

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Jan 7, 2026
@openshift-ci-robot
Copy link

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-aws-capi-techpreview
/test e2e-aws-ovn
/test e2e-aws-ovn-serial-1of2
/test e2e-aws-ovn-serial-2of2
/test e2e-aws-ovn-techpreview
/test e2e-aws-ovn-techpreview-upgrade
/test e2e-azure-capi-techpreview
/test e2e-azure-ovn-techpreview
/test e2e-azure-ovn-techpreview-upgrade
/test e2e-gcp-capi-techpreview
/test e2e-gcp-ovn-techpreview
/test e2e-metal3-capi-techpreview
/test e2e-openstack-capi-techpreview
/test e2e-openstack-ovn-techpreview
/test e2e-vsphere-capi-techpreview
/test regression-clusterinfra-aws-ipi-techpreview-capi

@openshift-ci-robot
Copy link

/retest-required

Remaining retests: 0 against base HEAD f975124 and 2 for PR HEAD 8b854d4 in total

@damdo
Copy link
Member

damdo commented Jan 7, 2026

/retest

@openshift-ci-robot
Copy link

/retest-required

Remaining retests: 0 against base HEAD 433fd8b and 1 for PR HEAD 8b854d4 in total

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jan 8, 2026

@miyadav: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-metal3-capi-techpreview 8b854d4 link false /test e2e-metal3-capi-techpreview
ci/prow/e2e-openstack-ovn-techpreview 8b854d4 link true /test e2e-openstack-ovn-techpreview

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@openshift-ci-robot
Copy link

/retest-required

Remaining retests: 0 against base HEAD 2d56218 and 0 for PR HEAD 8b854d4 in total

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. verified Signifies that the PR passed pre-merge verification criteria

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants