Skip to content

Commit bb5a6ad

Browse files
Merge pull request #125 from pnguyen44/HYPERFLEET-841/validate-condition-status
HYPERFLEET-841 - fix: filter invalid condition status from GET responses
2 parents f8d3d4c + 3dcf425 commit bb5a6ad

4 files changed

Lines changed: 69 additions & 5 deletions

File tree

pkg/api/presenters/adapter_status.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,20 @@ func PresentAdapterStatus(adapterStatus *api.AdapterStatus) (openapi.AdapterStat
8282
}
8383
}
8484

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{
85+
// Convert domain AdapterConditions to openapi format, filtering out
86+
// conditions with empty/invalid status (legacy data before validation was added).
87+
openapiConditions := make([]openapi.AdapterCondition, 0, len(conditions))
88+
for _, cond := range conditions {
89+
if !cond.Status.IsValid() {
90+
continue
91+
}
92+
openapiConditions = append(openapiConditions, openapi.AdapterCondition{
8993
Type: cond.Type,
9094
Status: openapi.AdapterConditionStatus(cond.Status),
9195
Reason: cond.Reason,
9296
Message: cond.Message,
9397
LastTransitionTime: cond.LastTransitionTime,
94-
}
98+
})
9599
}
96100

97101
// 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)

pkg/api/status_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ const (
2121
AdapterConditionUnknown AdapterConditionStatus = "Unknown"
2222
)
2323

24+
// IsValid returns true if the status is one of the accepted enum values (True, False, Unknown).
25+
func (s AdapterConditionStatus) IsValid() bool {
26+
return s == AdapterConditionTrue || s == AdapterConditionFalse || s == AdapterConditionUnknown
27+
}
28+
2429
// Condition type constants
2530
const (
2631
ConditionTypeAvailable = "Available"

pkg/api/status_types_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ func TestAdapterConditionStatus_Constants(t *testing.T) {
3333
// which has "True", "False", and "Unknown" values
3434
}
3535

36+
// TestAdapterConditionStatus_IsValid verifies that IsValid accepts valid statuses and rejects invalid ones
37+
func TestAdapterConditionStatus_IsValid(t *testing.T) {
38+
RegisterTestingT(t)
39+
40+
Expect(AdapterConditionTrue.IsValid()).To(BeTrue())
41+
Expect(AdapterConditionFalse.IsValid()).To(BeTrue())
42+
Expect(AdapterConditionUnknown.IsValid()).To(BeTrue())
43+
44+
Expect(AdapterConditionStatus("").IsValid()).To(BeFalse())
45+
Expect(AdapterConditionStatus("garbage").IsValid()).To(BeFalse())
46+
Expect(AdapterConditionStatus("true").IsValid()).To(BeFalse())
47+
}
48+
3649
// TestAdapterConditionStatus_StringConversion tests type casting to/from string
3750
func TestAdapterConditionStatus_StringConversion(t *testing.T) {
3851
RegisterTestingT(t)

0 commit comments

Comments
 (0)