Skip to content

Commit 839e1c4

Browse files
committed
HYPERFLEET-841 - fix: filter invalid condition
status from GET responses
1 parent 20f9bf8 commit 839e1c4

2 files changed

Lines changed: 60 additions & 5 deletions

File tree

pkg/api/presenters/adapter_status.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ import (
1010
"gorm.io/datatypes"
1111
)
1212

13+
func isValidAdapterConditionStatus(status api.AdapterConditionStatus) bool {
14+
switch status {
15+
case api.AdapterConditionTrue, api.AdapterConditionFalse, api.AdapterConditionUnknown:
16+
return true
17+
default:
18+
return false
19+
}
20+
}
21+
1322
// ConvertAdapterStatus converts openapi.AdapterStatusCreateRequest to api.AdapterStatus (GORM model)
1423
func ConvertAdapterStatus(
1524
resourceType, resourceID string,
@@ -82,16 +91,20 @@ func PresentAdapterStatus(adapterStatus *api.AdapterStatus) (openapi.AdapterStat
8291
}
8392
}
8493

85-
// Convert domain AdapterConditions to openapi format
86-
openapiConditions := make([]openapi.AdapterCondition, len(conditions))
87-
for i, cond := range conditions {
88-
openapiConditions[i] = openapi.AdapterCondition{
94+
// Convert domain AdapterConditions to openapi format, filtering out
95+
// conditions with empty/invalid status (legacy data before validation was added).
96+
openapiConditions := make([]openapi.AdapterCondition, 0, len(conditions))
97+
for _, cond := range conditions {
98+
if !isValidAdapterConditionStatus(cond.Status) {
99+
continue
100+
}
101+
openapiConditions = append(openapiConditions, openapi.AdapterCondition{
89102
Type: cond.Type,
90103
Status: openapi.AdapterConditionStatus(cond.Status),
91104
Reason: cond.Reason,
92105
Message: cond.Message,
93106
LastTransitionTime: cond.LastTransitionTime,
94-
}
107+
})
95108
}
96109

97110
// Unmarshal Data

pkg/api/presenters/adapter_status_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,48 @@ func TestConvertAndPresent_RoundTrip(t *testing.T) {
457457
Expect(*result.Metadata.JobName).To(Equal(*originalReq.Metadata.JobName))
458458
}
459459

460+
// TestPresentAdapterStatus_FiltersInvalidConditionStatus verifies that conditions with
461+
// empty or invalid status values (legacy data) are excluded from GET responses.
462+
func TestPresentAdapterStatus_FiltersInvalidConditionStatus(t *testing.T) {
463+
RegisterTestingT(t)
464+
465+
now := time.Now()
466+
reason := "Healthy"
467+
message := "All good"
468+
469+
conditions := []api.AdapterCondition{
470+
// Valid — should be kept
471+
{Type: "Health", Status: api.AdapterConditionTrue, Reason: &reason, Message: &message, LastTransitionTime: now},
472+
{Type: "Available", Status: api.AdapterConditionFalse, LastTransitionTime: now},
473+
{Type: "Ready", Status: api.AdapterConditionUnknown, LastTransitionTime: now},
474+
475+
// Invalid — should be filtered out (legacy data)
476+
{Type: "Applied", Status: "", LastTransitionTime: now},
477+
{Type: "Reconciled", Status: "garbage", LastTransitionTime: now},
478+
}
479+
conditionsJSON, _ := json.Marshal(conditions)
480+
481+
adapterStatus := &api.AdapterStatus{
482+
ResourceType: "Cluster",
483+
ResourceID: "cluster-legacy",
484+
Adapter: "test-adapter",
485+
ObservedGeneration: 1,
486+
Conditions: conditionsJSON,
487+
Data: []byte("{}"),
488+
CreatedTime: now,
489+
LastReportTime: now,
490+
}
491+
492+
result, err := PresentAdapterStatus(adapterStatus)
493+
Expect(err).To(BeNil())
494+
495+
Expect(result.Conditions).To(HaveLen(3))
496+
for _, cond := range result.Conditions {
497+
Expect(cond.Type).ToNot(Equal("Applied"))
498+
Expect(cond.Type).ToNot(Equal("Reconciled"))
499+
}
500+
}
501+
460502
// TestPresentAdapterStatus_MalformedConditions tests error handling for malformed Conditions JSON
461503
func TestPresentAdapterStatus_MalformedConditions(t *testing.T) {
462504
RegisterTestingT(t)

0 commit comments

Comments
 (0)