-
Notifications
You must be signed in to change notification settings - Fork 12
Update lastTransitionTime for volume and nic in the machineCondition
#1428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ import ( | |
| "context" | ||
| "errors" | ||
| "fmt" | ||
| "sort" | ||
| "strconv" | ||
|
|
||
| "github.com/go-logr/logr" | ||
|
|
@@ -504,7 +505,8 @@ func (r *MachineReconciler) updateMachineStatus(ctx context.Context, machine *co | |
| machine.Status.ObservedGeneration = generation | ||
| machine.Status.Volumes = volumeStatuses | ||
| machine.Status.NetworkInterfaces = nicStatuses | ||
| machine.Status.Conditions = r.computeMachineConditions(state, volumeStatuses, nicStatuses, now) | ||
| computedConds := r.computeMachineConditions(state, volumeStatuses, nicStatuses, now) | ||
| machine.Status.Conditions = r.mergeMachineConditions(machine.Status.Conditions, computedConds) | ||
|
|
||
| if err := r.Status().Patch(ctx, machine, client.MergeFrom(base)); err != nil { | ||
| return fmt.Errorf("error patching status: %w", err) | ||
|
|
@@ -551,7 +553,7 @@ func (r *MachineReconciler) computeMachineReadyCondition(state computev1alpha1.M | |
| } | ||
|
|
||
| return computev1alpha1.MachineCondition{ | ||
| Type: "Ready", | ||
| Type: computev1alpha1.MachineConditionReady, | ||
| Status: status, | ||
| Reason: reason, | ||
| Message: message, | ||
|
|
@@ -565,22 +567,42 @@ func (r *MachineReconciler) computeVolumesReadyCondition(volumeStatuses []comput | |
| } | ||
|
|
||
| status, reason, message := corev1.ConditionTrue, "VolumesReady", "All volumes are ready" | ||
| var lastTransitionTime *metav1.Time | ||
|
|
||
| for _, vs := range volumeStatuses { | ||
| volume := &vs.VolumeRef | ||
| volName := volume.Name | ||
| if volName == "" { //if local-disk volume is used, where no actual volume resource exists | ||
| volName = vs.Name | ||
| } | ||
| if vs.State != computev1alpha1.VolumeStateAttached { | ||
| status = corev1.ConditionFalse | ||
| reason = fmt.Sprintf("VolumeNotReady: %s", vs.Name) | ||
| message = fmt.Sprintf("Volume %s is not attached (state: %s)", vs.Name, vs.State) | ||
| reason = fmt.Sprintf("VolumeNotReady: %s", volName) | ||
| message = fmt.Sprintf("Volume %s is not attached (state: %s)", volName, vs.State) | ||
| lastTransitionTime = vs.LastStateTransitionTime | ||
| break | ||
| } | ||
|
Rohit-0505 marked this conversation as resolved.
|
||
| } | ||
|
|
||
| if status == corev1.ConditionTrue { | ||
| for _, vs := range volumeStatuses { | ||
| if vs.LastStateTransitionTime != nil && (lastTransitionTime == nil || vs.LastStateTransitionTime.After(lastTransitionTime.Time)) { | ||
| lastTransitionTime = vs.LastStateTransitionTime | ||
| } | ||
| } | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| transitionTime := now | ||
| if lastTransitionTime != nil { | ||
| transitionTime = *lastTransitionTime | ||
| } | ||
|
|
||
| return computev1alpha1.MachineCondition{ | ||
| Type: computev1alpha1.MachineConditionType("VolumesReady"), | ||
| Type: computev1alpha1.MachineConditionVolumesReady, | ||
| Status: status, | ||
| Reason: reason, | ||
| Message: message, | ||
| LastTransitionTime: now, | ||
| LastTransitionTime: transitionTime, | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -590,25 +612,89 @@ func (r *MachineReconciler) computeNetworkInterfacesReadyCondition(nicStatuses [ | |
| } | ||
|
|
||
| status, reason, message := corev1.ConditionTrue, "NetworkInterfacesReady", "All network interfaces are ready" | ||
| var lastTransitionTime *metav1.Time | ||
|
|
||
| for _, nicStatus := range nicStatuses { | ||
| nic := &nicStatus.NetworkInterfaceRef | ||
| if nicStatus.State != computev1alpha1.NetworkInterfaceStateAttached { | ||
| status = corev1.ConditionFalse | ||
| reason = fmt.Sprintf("NetworkInterfaceNotReady: %s", nicStatus.Name) | ||
| message = fmt.Sprintf("Network interface %s is not attached (state: %s)", nicStatus.Name, nicStatus.State) | ||
| reason = fmt.Sprintf("NetworkInterfaceNotReady: %s", nic.Name) | ||
| message = fmt.Sprintf("Network interface %s is not attached (state: %s)", nic.Name, nicStatus.State) | ||
| lastTransitionTime = nicStatus.LastStateTransitionTime | ||
| break | ||
| } | ||
|
Rohit-0505 marked this conversation as resolved.
|
||
| } | ||
|
|
||
| if status == corev1.ConditionTrue { | ||
| for _, nicStatus := range nicStatuses { | ||
| if nicStatus.LastStateTransitionTime != nil && (lastTransitionTime == nil || nicStatus.LastStateTransitionTime.After(lastTransitionTime.Time)) { | ||
| lastTransitionTime = nicStatus.LastStateTransitionTime | ||
| } | ||
| } | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| transitionTime := now | ||
| if lastTransitionTime != nil { | ||
| transitionTime = *lastTransitionTime | ||
| } | ||
|
|
||
| return computev1alpha1.MachineCondition{ | ||
| Type: computev1alpha1.MachineConditionType("NetworkInterfacesReady"), | ||
| Type: computev1alpha1.MachineConditionNetworkInterfacesReady, | ||
| Status: status, | ||
| Reason: reason, | ||
| Message: message, | ||
| LastTransitionTime: now, | ||
| LastTransitionTime: transitionTime, | ||
| } | ||
| } | ||
|
|
||
| func (r *MachineReconciler) mergeMachineConditions( | ||
| existing []computev1alpha1.MachineCondition, | ||
| current []computev1alpha1.MachineCondition, | ||
| ) []computev1alpha1.MachineCondition { | ||
| updated := append([]computev1alpha1.MachineCondition{}, existing...) | ||
|
|
||
| lastStatus := make(map[string]corev1.ConditionStatus, len(existing)) | ||
| for _, c := range existing { | ||
| lastStatus[string(c.Type)] = c.Status | ||
| } | ||
|
|
||
| for _, newCond := range current { | ||
| conditionType := string(newCond.Type) | ||
| if prev, ok := lastStatus[conditionType]; !ok || prev != newCond.Status { | ||
| updated = append(updated, newCond) | ||
| lastStatus[conditionType] = newCond.Status | ||
| } | ||
| } | ||
|
|
||
| // Group conditions by type and keep only the latest 10 per type (by LastTransitionTime) | ||
| const maxConditionsPerType = 10 | ||
| conditionsByType := make(map[string][]computev1alpha1.MachineCondition) | ||
| for _, cond := range updated { | ||
| condType := string(cond.Type) | ||
| conditionsByType[condType] = append(conditionsByType[condType], cond) | ||
| } | ||
|
|
||
| var result []computev1alpha1.MachineCondition | ||
| // Sort condition types for deterministic ordering | ||
| types := make([]string, 0, len(conditionsByType)) | ||
| for t := range conditionsByType { | ||
| types = append(types, t) | ||
| } | ||
| sort.Strings(types) | ||
| for _, t := range types { | ||
| conds := conditionsByType[t] | ||
| sort.Slice(conds, func(i, j int) bool { | ||
| return conds[i].LastTransitionTime.Before(&conds[j].LastTransitionTime) | ||
| }) | ||
| if len(conds) > maxConditionsPerType { | ||
| conds = conds[len(conds)-maxConditionsPerType:] | ||
| } | ||
| result = append(result, conds...) | ||
| } | ||
|
|
||
| return result | ||
| } | ||
|
Comment on lines
+650
to
+696
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check if there's documentation or comments about condition history retention behavior
rg -n -i "stale|history|retain|persist" poollet/machinepoollet/controllers/machine_controller.go
# Check if there are tests covering the stale condition scenario
rg -n -A 5 "mergeMachineConditions" poollet/machinepoollet/controllers/machine_controller_test.goRepository: ironcore-dev/ironcore Length of output: 47 🏁 Script executed: #!/bin/bash
# List files to understand directory structure
find . -name "machine_controller.go" -type f
find . -name "machine_controller_test.go" -type f
# Check if the files exist and look for any comments around condition handling
find . -name "machine_controller.go" -type f -exec head -700 {} \; | tail -100Repository: ironcore-dev/ironcore Length of output: 3575 🏁 Script executed: #!/bin/bash
# Check for mergeMachineConditions tests
grep -n -A 20 "mergeMachineConditions" ./poollet/machinepoollet/controllers/machine_controller_test.go
# Check how current conditions are generated - look for function calls to condition functions
grep -n "computeVolumesReadyCondition\|computeNetworkInterfacesReadyCondition" ./poollet/machinepoollet/controllers/machine_controller.go
# Find where mergeMachineConditions is called to understand the flow
grep -n "mergeMachineConditions" ./poollet/machinepoollet/controllers/machine_controller.goRepository: ironcore-dev/ironcore Length of output: 728 🏁 Script executed: #!/bin/bash
# Read the computeVolumesReadyCondition function to see what it returns when empty
sed -n '564,608p' ./poollet/machinepoollet/controllers/machine_controller.go
# Check where computedConds is built to understand the full flow
sed -n '520,545p' ./poollet/machinepoollet/controllers/machine_controller.goRepository: ironcore-dev/ironcore Length of output: 2410 🏁 Script executed: #!/bin/bash
# Search for mergeMachineConditions tests more thoroughly
grep -n "mergeMachineConditions\|TestMergeMachine" ./poollet/machinepoollet/controllers/machine_controller_test.go
# Also check if there are any tests about condition removal or stale conditions
grep -n -i "stale\|remove.*condition\|condition.*remov" ./poollet/machinepoollet/controllers/machine_controller_test.go
# Look at the actual test file around mergeMachineConditions if it exists
grep -n -B 5 -A 30 "func.*mergeMachine" ./poollet/machinepoollet/controllers/machine_controller_test.goRepository: ironcore-dev/ironcore Length of output: 47 🏁 Script executed: #!/bin/bash
# List test functions in the test file
grep -n "^func Test" ./poollet/machinepoollet/controllers/machine_controller_test.go | head -20
# Get overview of test file
wc -l ./poollet/machinepoollet/controllers/machine_controller_test.go
# Search for any mention of conditions in tests
grep -n -i "condition" ./poollet/machinepoollet/controllers/machine_controller_test.go | head -20Repository: ironcore-dev/ironcore Length of output: 1454 🏁 Script executed: #!/bin/bash
# Search for any documentation files mentioning conditions
find . -name "*.md" -type f -exec grep -l "condition" {} \; | head -10
# Search for any design docs in common locations
find . -path "*/docs/*" -name "*.md" -type f 2>/dev/null | head -10
# Check if there are any comments in the reconciliation logic about condition handling
sed -n '490,550p' ./poollet/machinepoollet/controllers/machine_controller.go | grep -n -i "condition\|TODO\|FIXME"
# Look at the entire reconciliation function to understand condition flow
grep -n "func (r \*MachineReconciler) Reconcile" ./poollet/machinepoollet/controllers/machine_controller.goRepository: ironcore-dev/ironcore Length of output: 1857 🏁 Script executed: #!/bin/bash
# Get the full mergeMachineConditions function and surrounding context
sed -n '650,700p' ./poollet/machinepoollet/controllers/machine_controller.go
# Check if there's any cleanup or removal logic elsewhere
grep -n "Status.Conditions\s*=" ./poollet/machinepoollet/controllers/machine_controller.go | head -10Repository: ironcore-dev/ironcore Length of output: 1851 🏁 Script executed: #!/bin/bash
# Search for condition-related documentation
grep -n -i "condition\|history" ./docs/architecture/*.md ./docs/concepts/*.md 2>/dev/null | grep -i "condition"
# Check if there are any proposals or design decisions about conditions
grep -r -i "condition.*history\|audit\|retain" ./docs/proposals/ 2>/dev/null
# Look for any comments in related files about condition lifecycle
grep -n -i "stale\|obsolete\|expired\|cleanup" ./poollet/machinepoollet/controllers/*.goRepository: ironcore-dev/ironcore Length of output: 3404 Remove stale conditions when their corresponding resources are deleted. The current merge logic preserves all existing conditions and only appends new ones when status changes. This causes conditions from removed resources (e.g., While the Consider either: (1) explicitly removing condition types that are no longer applicable (when a resource type goes from having items to zero), or (2) adding a mechanism to mark/filter stale conditions so they're preserved for audit/history but clearly distinguished from current state. 🤖 Prompt for AI Agents |
||
|
|
||
| func (r *MachineReconciler) prepareIRIPower(power computev1alpha1.Power) (iri.Power, error) { | ||
| switch power { | ||
| case computev1alpha1.PowerOn: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.