From 54160549904d66743c32260375ab517ca61b46f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michaela=20Pa=C5=99ilov=C3=A1?= Date: Wed, 17 Dec 2025 14:06:20 +0100 Subject: [PATCH] feat: propagate JSON unmarshal errors --- pkg/api/presenters/adapter_status.go | 16 +++-- pkg/api/presenters/adapter_status_test.go | 88 +++++++++++++++++++++-- pkg/api/presenters/cluster.go | 16 +++-- pkg/api/presenters/cluster_test.go | 75 +++++++++++++++++-- pkg/api/presenters/node_pool.go | 16 +++-- pkg/api/presenters/node_pool_test.go | 81 +++++++++++++++++++-- pkg/handlers/cluster.go | 25 +++++-- pkg/handlers/cluster_nodepools.go | 19 +++-- pkg/handlers/cluster_status.go | 11 ++- pkg/handlers/node_pool.go | 25 +++++-- pkg/handlers/nodepool_status.go | 11 ++- 11 files changed, 331 insertions(+), 52 deletions(-) diff --git a/pkg/api/presenters/adapter_status.go b/pkg/api/presenters/adapter_status.go index 0b2482e..6019836 100644 --- a/pkg/api/presenters/adapter_status.go +++ b/pkg/api/presenters/adapter_status.go @@ -73,11 +73,13 @@ func ConvertAdapterStatus( } // PresentAdapterStatus converts api.AdapterStatus (GORM model) to openapi.AdapterStatus -func PresentAdapterStatus(adapterStatus *api.AdapterStatus) openapi.AdapterStatus { +func PresentAdapterStatus(adapterStatus *api.AdapterStatus) (openapi.AdapterStatus, error) { // Unmarshal Conditions var conditions []api.AdapterCondition if len(adapterStatus.Conditions) > 0 { - _ = json.Unmarshal(adapterStatus.Conditions, &conditions) + if err := json.Unmarshal(adapterStatus.Conditions, &conditions); err != nil { + return openapi.AdapterStatus{}, fmt.Errorf("failed to unmarshal adapter status conditions: %w", err) + } } // Convert domain AdapterConditions to openapi format @@ -95,13 +97,17 @@ func PresentAdapterStatus(adapterStatus *api.AdapterStatus) openapi.AdapterStatu // Unmarshal Data var data map[string]map[string]interface{} if len(adapterStatus.Data) > 0 { - _ = json.Unmarshal(adapterStatus.Data, &data) + if err := json.Unmarshal(adapterStatus.Data, &data); err != nil { + return openapi.AdapterStatus{}, fmt.Errorf("failed to unmarshal adapter status data: %w", err) + } } // Unmarshal Metadata var metadata *openapi.AdapterStatusBaseMetadata if len(adapterStatus.Metadata) > 0 { - _ = json.Unmarshal(adapterStatus.Metadata, &metadata) + if err := json.Unmarshal(adapterStatus.Metadata, &metadata); err != nil { + return openapi.AdapterStatus{}, fmt.Errorf("failed to unmarshal adapter status metadata: %w", err) + } } // Set default times if nil (shouldn't happen in normal operation) @@ -123,5 +129,5 @@ func PresentAdapterStatus(adapterStatus *api.AdapterStatus) openapi.AdapterStatu Metadata: metadata, CreatedTime: createdTime, LastReportTime: lastReportTime, - } + }, nil } diff --git a/pkg/api/presenters/adapter_status_test.go b/pkg/api/presenters/adapter_status_test.go index c131637..06204e8 100644 --- a/pkg/api/presenters/adapter_status_test.go +++ b/pkg/api/presenters/adapter_status_test.go @@ -266,7 +266,8 @@ func TestPresentAdapterStatus_Complete(t *testing.T) { LastReportTime: &now, } - result := PresentAdapterStatus(adapterStatus) + result, err := PresentAdapterStatus(adapterStatus) + Expect(err).To(BeNil()) // Verify basic fields Expect(result.Adapter).To(Equal("aws-adapter")) @@ -305,7 +306,8 @@ func TestPresentAdapterStatus_NilTimestamps(t *testing.T) { LastReportTime: nil, // Nil timestamp } - result := PresentAdapterStatus(adapterStatus) + result, err := PresentAdapterStatus(adapterStatus) + Expect(err).To(BeNil()) // Verify zero time.Time is returned (not nil) Expect(result.CreatedTime.IsZero()).To(BeTrue()) @@ -328,7 +330,8 @@ func TestPresentAdapterStatus_EmptyConditions(t *testing.T) { LastReportTime: &now, } - result := PresentAdapterStatus(adapterStatus) + result, err := PresentAdapterStatus(adapterStatus) + Expect(err).To(BeNil()) Expect(result.Conditions).ToNot(BeNil()) Expect(len(result.Conditions)).To(Equal(0)) @@ -350,7 +353,8 @@ func TestPresentAdapterStatus_EmptyData(t *testing.T) { LastReportTime: &now, } - result := PresentAdapterStatus(adapterStatus) + result, err := PresentAdapterStatus(adapterStatus) + Expect(err).To(BeNil()) Expect(result.Data).ToNot(BeNil()) Expect(len(result.Data)).To(Equal(0)) @@ -391,7 +395,8 @@ func TestPresentAdapterStatus_ConditionStatusConversion(t *testing.T) { LastReportTime: &now, } - result := PresentAdapterStatus(adapterStatus) + result, err := PresentAdapterStatus(adapterStatus) + Expect(err).To(BeNil()) Expect(len(result.Conditions)).To(Equal(1)) Expect(result.Conditions[0].Status).To(Equal(tc.expectedOpenAPI)) @@ -409,7 +414,8 @@ func TestConvertAndPresent_RoundTrip(t *testing.T) { Expect(err).To(BeNil()) // Present from domain back to OpenAPI - result := PresentAdapterStatus(adapterStatus) + result, err := PresentAdapterStatus(adapterStatus) + Expect(err).To(BeNil()) // Verify data integrity Expect(result.Adapter).To(Equal(originalReq.Adapter)) @@ -429,3 +435,73 @@ func TestConvertAndPresent_RoundTrip(t *testing.T) { Expect(result.Metadata).ToNot(BeNil()) Expect(*result.Metadata.JobName).To(Equal(*originalReq.Metadata.JobName)) } + +// TestPresentAdapterStatus_MalformedConditions tests error handling for malformed Conditions JSON +func TestPresentAdapterStatus_MalformedConditions(t *testing.T) { + RegisterTestingT(t) + + now := time.Now() + adapterStatus := &api.AdapterStatus{ + ResourceType: "Cluster", + ResourceID: "cluster-123", + Adapter: "test-adapter", + ObservedGeneration: 5, + Conditions: []byte("{invalid json}"), // Malformed JSON + Data: []byte("{}"), + CreatedTime: &now, + LastReportTime: &now, + } + adapterStatus.ID = "adapter-status-malformed-conditions" + + _, err := PresentAdapterStatus(adapterStatus) + + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("failed to unmarshal adapter status conditions")) +} + +// TestPresentAdapterStatus_MalformedData tests error handling for malformed Data JSON +func TestPresentAdapterStatus_MalformedData(t *testing.T) { + RegisterTestingT(t) + + now := time.Now() + adapterStatus := &api.AdapterStatus{ + ResourceType: "Cluster", + ResourceID: "cluster-456", + Adapter: "test-adapter", + ObservedGeneration: 5, + Conditions: []byte("[]"), + Data: []byte("{not valid json"), // Malformed JSON + CreatedTime: &now, + LastReportTime: &now, + } + adapterStatus.ID = "adapter-status-malformed-data" + + _, err := PresentAdapterStatus(adapterStatus) + + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("failed to unmarshal adapter status data")) +} + +// TestPresentAdapterStatus_MalformedMetadata tests error handling for malformed Metadata JSON +func TestPresentAdapterStatus_MalformedMetadata(t *testing.T) { + RegisterTestingT(t) + + now := time.Now() + adapterStatus := &api.AdapterStatus{ + ResourceType: "Cluster", + ResourceID: "cluster-789", + Adapter: "test-adapter", + ObservedGeneration: 5, + Conditions: []byte("[]"), + Data: []byte("{}"), + Metadata: []byte("[{incomplete"), // Malformed JSON + CreatedTime: &now, + LastReportTime: &now, + } + adapterStatus.ID = "adapter-status-malformed-metadata" + + _, err := PresentAdapterStatus(adapterStatus) + + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("failed to unmarshal adapter status metadata")) +} diff --git a/pkg/api/presenters/cluster.go b/pkg/api/presenters/cluster.go index 01a9507..fe5d2df 100644 --- a/pkg/api/presenters/cluster.go +++ b/pkg/api/presenters/cluster.go @@ -48,23 +48,29 @@ func ConvertCluster(req *openapi.ClusterCreateRequest, createdBy string) (*api.C } // PresentCluster converts api.Cluster (GORM model) to openapi.Cluster -func PresentCluster(cluster *api.Cluster) openapi.Cluster { +func PresentCluster(cluster *api.Cluster) (openapi.Cluster, error) { // Unmarshal Spec var spec map[string]interface{} if len(cluster.Spec) > 0 { - _ = json.Unmarshal(cluster.Spec, &spec) + if err := json.Unmarshal(cluster.Spec, &spec); err != nil { + return openapi.Cluster{}, fmt.Errorf("failed to unmarshal cluster spec: %w", err) + } } // Unmarshal Labels var labels map[string]string if len(cluster.Labels) > 0 { - _ = json.Unmarshal(cluster.Labels, &labels) + if err := json.Unmarshal(cluster.Labels, &labels); err != nil { + return openapi.Cluster{}, fmt.Errorf("failed to unmarshal cluster labels: %w", err) + } } // Unmarshal StatusConditions var statusConditions []api.ResourceCondition if len(cluster.StatusConditions) > 0 { - _ = json.Unmarshal(cluster.StatusConditions, &statusConditions) + if err := json.Unmarshal(cluster.StatusConditions, &statusConditions); err != nil { + return openapi.Cluster{}, fmt.Errorf("failed to unmarshal cluster status conditions: %w", err) + } } // Generate Href if not set (fallback) @@ -127,5 +133,5 @@ func PresentCluster(cluster *api.Cluster) openapi.Cluster { LastUpdatedTime: lastUpdatedTime, } - return result + return result, nil } diff --git a/pkg/api/presenters/cluster_test.go b/pkg/api/presenters/cluster_test.go index 9d6293b..c2100fa 100644 --- a/pkg/api/presenters/cluster_test.go +++ b/pkg/api/presenters/cluster_test.go @@ -203,7 +203,8 @@ func TestPresentCluster_Complete(t *testing.T) { cluster.CreatedTime = now cluster.UpdatedTime = now - result := PresentCluster(cluster) + result, err := PresentCluster(cluster) + Expect(err).To(BeNil()) // Verify basic fields Expect(*result.Id).To(Equal("cluster-abc123")) @@ -249,7 +250,8 @@ func TestPresentCluster_HrefGeneration(t *testing.T) { } cluster.ID = "cluster-xyz789" - result := PresentCluster(cluster) + result, err := PresentCluster(cluster) + Expect(err).To(BeNil()) Expect(*result.Href).To(Equal("/api/hyperfleet/v1/clusters/cluster-xyz789")) } @@ -268,7 +270,8 @@ func TestPresentCluster_EmptyStatusPhase(t *testing.T) { } cluster.ID = "cluster-empty-phase" - result := PresentCluster(cluster) + result, err := PresentCluster(cluster) + Expect(err).To(BeNil()) // Should use NOT_READY as default Expect(result.Status.Phase).To(Equal(openapi.NOT_READY)) @@ -292,7 +295,8 @@ func TestPresentCluster_NilStatusTimestamps(t *testing.T) { cluster.CreatedTime = now cluster.UpdatedTime = now - result := PresentCluster(cluster) + result, err := PresentCluster(cluster) + Expect(err).To(BeNil()) // Verify zero time.Time is returned (not nil) Expect(result.Status.LastTransitionTime.IsZero()).To(BeTrue()) @@ -345,7 +349,8 @@ func TestPresentCluster_StatusConditionsConversion(t *testing.T) { cluster.CreatedTime = now cluster.UpdatedTime = now - result := PresentCluster(cluster) + result, err := PresentCluster(cluster) + Expect(err).To(BeNil()) // Verify both conditions converted correctly Expect(len(result.Status.Conditions)).To(Equal(2)) @@ -380,7 +385,8 @@ func TestConvertAndPresentCluster_RoundTrip(t *testing.T) { cluster.UpdatedTime = now // Present from domain back to OpenAPI - result := PresentCluster(cluster) + result, err := PresentCluster(cluster) + Expect(err).To(BeNil()) // Verify data integrity Expect(*result.Id).To(Equal("cluster-roundtrip-123")) @@ -401,3 +407,60 @@ func TestConvertAndPresentCluster_RoundTrip(t *testing.T) { Expect(result.Status.ObservedGeneration).To(Equal(int32(0))) Expect(len(result.Status.Conditions)).To(Equal(0)) } + +// TestPresentCluster_MalformedSpec tests error handling for malformed Spec JSON +func TestPresentCluster_MalformedSpec(t *testing.T) { + RegisterTestingT(t) + + cluster := &api.Cluster{ + Kind: "Cluster", + Name: "malformed-spec-cluster", + Spec: []byte("{invalid json}"), // Malformed JSON + Labels: []byte("{}"), + StatusConditions: []byte("[]"), + } + cluster.ID = "cluster-malformed-spec" + + _, err := PresentCluster(cluster) + + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("failed to unmarshal cluster spec")) +} + +// TestPresentCluster_MalformedLabels tests error handling for malformed Labels JSON +func TestPresentCluster_MalformedLabels(t *testing.T) { + RegisterTestingT(t) + + cluster := &api.Cluster{ + Kind: "Cluster", + Name: "malformed-labels-cluster", + Spec: []byte("{}"), + Labels: []byte("{not valid json"), // Malformed JSON + StatusConditions: []byte("[]"), + } + cluster.ID = "cluster-malformed-labels" + + _, err := PresentCluster(cluster) + + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("failed to unmarshal cluster labels")) +} + +// TestPresentCluster_MalformedStatusConditions tests error handling for malformed StatusConditions JSON +func TestPresentCluster_MalformedStatusConditions(t *testing.T) { + RegisterTestingT(t) + + cluster := &api.Cluster{ + Kind: "Cluster", + Name: "malformed-conditions-cluster", + Spec: []byte("{}"), + Labels: []byte("{}"), + StatusConditions: []byte("[{incomplete"), // Malformed JSON + } + cluster.ID = "cluster-malformed-conditions" + + _, err := PresentCluster(cluster) + + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("failed to unmarshal cluster status conditions")) +} diff --git a/pkg/api/presenters/node_pool.go b/pkg/api/presenters/node_pool.go index dd954b8..b4849a5 100644 --- a/pkg/api/presenters/node_pool.go +++ b/pkg/api/presenters/node_pool.go @@ -54,23 +54,29 @@ func ConvertNodePool(req *openapi.NodePoolCreateRequest, ownerID, createdBy stri } // PresentNodePool converts api.NodePool (GORM model) to openapi.NodePool -func PresentNodePool(nodePool *api.NodePool) openapi.NodePool { +func PresentNodePool(nodePool *api.NodePool) (openapi.NodePool, error) { // Unmarshal Spec var spec map[string]interface{} if len(nodePool.Spec) > 0 { - _ = json.Unmarshal(nodePool.Spec, &spec) + if err := json.Unmarshal(nodePool.Spec, &spec); err != nil { + return openapi.NodePool{}, fmt.Errorf("failed to unmarshal nodepool spec: %w", err) + } } // Unmarshal Labels var labels map[string]string if len(nodePool.Labels) > 0 { - _ = json.Unmarshal(nodePool.Labels, &labels) + if err := json.Unmarshal(nodePool.Labels, &labels); err != nil { + return openapi.NodePool{}, fmt.Errorf("failed to unmarshal nodepool labels: %w", err) + } } // Unmarshal StatusConditions var statusConditions []api.ResourceCondition if len(nodePool.StatusConditions) > 0 { - _ = json.Unmarshal(nodePool.StatusConditions, &statusConditions) + if err := json.Unmarshal(nodePool.StatusConditions, &statusConditions); err != nil { + return openapi.NodePool{}, fmt.Errorf("failed to unmarshal nodepool status conditions: %w", err) + } } // Generate Href if not set (fallback) @@ -145,5 +151,5 @@ func PresentNodePool(nodePool *api.NodePool) openapi.NodePool { LastUpdatedTime: lastUpdatedTime, } - return result + return result, nil } diff --git a/pkg/api/presenters/node_pool_test.go b/pkg/api/presenters/node_pool_test.go index e39229f..f70a87b 100644 --- a/pkg/api/presenters/node_pool_test.go +++ b/pkg/api/presenters/node_pool_test.go @@ -200,7 +200,8 @@ func TestPresentNodePool_Complete(t *testing.T) { nodePool.CreatedTime = now nodePool.UpdatedTime = now - result := PresentNodePool(nodePool) + result, err := PresentNodePool(nodePool) + Expect(err).To(BeNil()) // Verify basic fields Expect(*result.Id).To(Equal("nodepool-xyz")) @@ -250,7 +251,8 @@ func TestPresentNodePool_HrefGeneration(t *testing.T) { } nodePool.ID = "nodepool-test-123" - result := PresentNodePool(nodePool) + result, err := PresentNodePool(nodePool) + Expect(err).To(BeNil()) Expect(*result.Href).To(Equal("/api/hyperfleet/v1/clusters/cluster-owner-456/nodepools/nodepool-test-123")) } @@ -270,7 +272,8 @@ func TestPresentNodePool_OwnerHrefGeneration(t *testing.T) { } nodePool.ID = "nodepool-owner-test" - result := PresentNodePool(nodePool) + result, err := PresentNodePool(nodePool) + Expect(err).To(BeNil()) Expect(*result.OwnerReferences.Href).To(Equal("/api/hyperfleet/v1/clusters/cluster-owner-789")) } @@ -290,7 +293,8 @@ func TestPresentNodePool_OwnerReferences(t *testing.T) { } nodePool.ID = "nodepool-ref-456" - result := PresentNodePool(nodePool) + result, err := PresentNodePool(nodePool) + Expect(err).To(BeNil()) Expect(result.OwnerReferences.Id).ToNot(BeNil()) Expect(*result.OwnerReferences.Id).To(Equal("cluster-ref-123")) @@ -314,7 +318,8 @@ func TestPresentNodePool_EmptyStatusPhase(t *testing.T) { } nodePool.ID = "nodepool-empty-phase" - result := PresentNodePool(nodePool) + result, err := PresentNodePool(nodePool) + Expect(err).To(BeNil()) // Should use NOT_READY as default Expect(result.Status.Phase).To(Equal(openapi.NOT_READY)) @@ -367,7 +372,8 @@ func TestPresentNodePool_StatusConditionsConversion(t *testing.T) { nodePool.CreatedTime = now nodePool.UpdatedTime = now - result := PresentNodePool(nodePool) + result, err := PresentNodePool(nodePool) + Expect(err).To(BeNil()) // Verify both conditions converted correctly Expect(len(result.Status.Conditions)).To(Equal(2)) @@ -403,7 +409,8 @@ func TestConvertAndPresentNodePool_RoundTrip(t *testing.T) { nodePool.UpdatedTime = now // Present from domain back to OpenAPI - result := PresentNodePool(nodePool) + result, err := PresentNodePool(nodePool) + Expect(err).To(BeNil()) // Verify data integrity Expect(*result.Id).To(Equal("nodepool-roundtrip-123")) @@ -428,3 +435,63 @@ func TestConvertAndPresentNodePool_RoundTrip(t *testing.T) { Expect(result.Status.ObservedGeneration).To(Equal(int32(0))) Expect(len(result.Status.Conditions)).To(Equal(0)) } + +// TestPresentNodePool_MalformedSpec tests error handling for malformed Spec JSON +func TestPresentNodePool_MalformedSpec(t *testing.T) { + RegisterTestingT(t) + + nodePool := &api.NodePool{ + Kind: "NodePool", + Name: "malformed-spec-nodepool", + Spec: []byte("{invalid json}"), // Malformed JSON + Labels: []byte("{}"), + OwnerID: "cluster-123", + StatusConditions: []byte("[]"), + } + nodePool.ID = "nodepool-malformed-spec" + + _, err := PresentNodePool(nodePool) + + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("failed to unmarshal nodepool spec")) +} + +// TestPresentNodePool_MalformedLabels tests error handling for malformed Labels JSON +func TestPresentNodePool_MalformedLabels(t *testing.T) { + RegisterTestingT(t) + + nodePool := &api.NodePool{ + Kind: "NodePool", + Name: "malformed-labels-nodepool", + Spec: []byte("{}"), + Labels: []byte("{not valid json"), // Malformed JSON + OwnerID: "cluster-456", + StatusConditions: []byte("[]"), + } + nodePool.ID = "nodepool-malformed-labels" + + _, err := PresentNodePool(nodePool) + + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("failed to unmarshal nodepool labels")) +} + +// TestPresentNodePool_MalformedStatusConditions tests error handling for malformed StatusConditions JSON +func TestPresentNodePool_MalformedStatusConditions(t *testing.T) { + RegisterTestingT(t) + + nodePool := &api.NodePool{ + Kind: "NodePool", + Name: "malformed-conditions-nodepool", + Spec: []byte("{}"), + Labels: []byte("{}"), + OwnerID: "cluster-789", + StatusConditions: []byte("[{incomplete"), // Malformed JSON + } + nodePool.ID = "nodepool-malformed-conditions" + + _, err := PresentNodePool(nodePool) + + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("failed to unmarshal nodepool status conditions")) +} diff --git a/pkg/handlers/cluster.go b/pkg/handlers/cluster.go index fbd846d..3285c9e 100644 --- a/pkg/handlers/cluster.go +++ b/pkg/handlers/cluster.go @@ -47,7 +47,11 @@ func (h clusterHandler) Create(w http.ResponseWriter, r *http.Request) { if svcErr != nil { return nil, svcErr } - return presenters.PresentCluster(clusterModel), nil + presented, err := presenters.PresentCluster(clusterModel) + if err != nil { + return nil, errors.GeneralError("Failed to present cluster: %v", err) + } + return presented, nil }, handleError, } @@ -81,7 +85,11 @@ func (h clusterHandler) Patch(w http.ResponseWriter, r *http.Request) { if err != nil { return nil, err } - return presenters.PresentCluster(clusterModel), nil + presented, presErr := presenters.PresentCluster(clusterModel) + if presErr != nil { + return nil, errors.GeneralError("Failed to present cluster: %v", presErr) + } + return presented, nil }, handleError, } @@ -109,8 +117,11 @@ func (h clusterHandler) List(w http.ResponseWriter, r *http.Request) { } for _, cluster := range clusters { - converted := presenters.PresentCluster(&cluster) - clusterList.Items = append(clusterList.Items, converted) + presented, err := presenters.PresentCluster(&cluster) + if err != nil { + return nil, errors.GeneralError("Failed to present cluster: %v", err) + } + clusterList.Items = append(clusterList.Items, presented) } if listArgs.Fields != nil { filteredItems, err := presenters.SliceFilter(listArgs.Fields, clusterList.Items) @@ -136,7 +147,11 @@ func (h clusterHandler) Get(w http.ResponseWriter, r *http.Request) { return nil, err } - return presenters.PresentCluster(cluster), nil + presented, presErr := presenters.PresentCluster(cluster) + if presErr != nil { + return nil, errors.GeneralError("Failed to present cluster: %v", presErr) + } + return presented, nil }, } diff --git a/pkg/handlers/cluster_nodepools.go b/pkg/handlers/cluster_nodepools.go index 14cf484..a474e0e 100644 --- a/pkg/handlers/cluster_nodepools.go +++ b/pkg/handlers/cluster_nodepools.go @@ -57,8 +57,11 @@ func (h clusterNodePoolsHandler) List(w http.ResponseWriter, r *http.Request) { // Build list response items := make([]openapi.NodePool, 0, len(nodePools)) for _, nodePool := range nodePools { - converted := presenters.PresentNodePool(&nodePool) - items = append(items, converted) + presented, err := presenters.PresentNodePool(&nodePool) + if err != nil { + return nil, errors.GeneralError("Failed to present nodepool: %v", err) + } + items = append(items, presented) } nodePoolList := struct { @@ -114,7 +117,11 @@ func (h clusterNodePoolsHandler) Get(w http.ResponseWriter, r *http.Request) { return nil, errors.NotFound("NodePool '%s' not found for cluster '%s'", nodePoolID, clusterID) } - return presenters.PresentNodePool(nodePool), nil + presented, presErr := presenters.PresentNodePool(nodePool) + if presErr != nil { + return nil, errors.GeneralError("Failed to present nodepool: %v", presErr) + } + return presented, nil }, } @@ -153,7 +160,11 @@ func (h clusterNodePoolsHandler) Create(w http.ResponseWriter, r *http.Request) return nil, err } - return presenters.PresentNodePool(nodePoolModel), nil + presented, presErr := presenters.PresentNodePool(nodePoolModel) + if presErr != nil { + return nil, errors.GeneralError("Failed to present nodepool: %v", presErr) + } + return presented, nil }, handleError, } diff --git a/pkg/handlers/cluster_status.go b/pkg/handlers/cluster_status.go index af294cd..c202299 100644 --- a/pkg/handlers/cluster_status.go +++ b/pkg/handlers/cluster_status.go @@ -41,7 +41,11 @@ func (h clusterStatusHandler) List(w http.ResponseWriter, r *http.Request) { // Convert to OpenAPI models items := make([]openapi.AdapterStatus, 0, len(adapterStatuses)) for _, as := range adapterStatuses { - items = append(items, presenters.PresentAdapterStatus(as)) + presented, presErr := presenters.PresentAdapterStatus(as) + if presErr != nil { + return nil, errors.GeneralError("Failed to present adapter status: %v", presErr) + } + items = append(items, presented) } // Return list response with pagination metadata @@ -98,7 +102,10 @@ func (h clusterStatusHandler) Create(w http.ResponseWriter, r *http.Request) { log.Extra("cluster_id", clusterID).Extra("error", aggregateErr).Warning("Failed to aggregate cluster status") } - status := presenters.PresentAdapterStatus(adapterStatus) + status, presErr := presenters.PresentAdapterStatus(adapterStatus) + if presErr != nil { + return nil, errors.GeneralError("Failed to present adapter status: %v", presErr) + } return &status, nil }, handleError, diff --git a/pkg/handlers/node_pool.go b/pkg/handlers/node_pool.go index a57d88a..508c7a2 100644 --- a/pkg/handlers/node_pool.go +++ b/pkg/handlers/node_pool.go @@ -46,7 +46,11 @@ func (h nodePoolHandler) Create(w http.ResponseWriter, r *http.Request) { if err != nil { return nil, err } - return presenters.PresentNodePool(nodePoolModel), nil + presented, presErr := presenters.PresentNodePool(nodePoolModel) + if presErr != nil { + return nil, errors.GeneralError("Failed to present nodepool: %v", presErr) + } + return presented, nil }, handleError, } @@ -84,7 +88,11 @@ func (h nodePoolHandler) Patch(w http.ResponseWriter, r *http.Request) { if err != nil { return nil, err } - return presenters.PresentNodePool(nodePoolModel), nil + presented, presErr := presenters.PresentNodePool(nodePoolModel) + if presErr != nil { + return nil, errors.GeneralError("Failed to present nodepool: %v", presErr) + } + return presented, nil }, handleError, } @@ -107,8 +115,11 @@ func (h nodePoolHandler) List(w http.ResponseWriter, r *http.Request) { items := make([]openapi.NodePool, 0, len(nodePools)) for _, nodePool := range nodePools { - converted := presenters.PresentNodePool(&nodePool) - items = append(items, converted) + presented, err := presenters.PresentNodePool(&nodePool) + if err != nil { + return nil, errors.GeneralError("Failed to present nodepool: %v", err) + } + items = append(items, presented) } nodePoolList := struct { @@ -148,7 +159,11 @@ func (h nodePoolHandler) Get(w http.ResponseWriter, r *http.Request) { return nil, err } - return presenters.PresentNodePool(nodePool), nil + presented, presErr := presenters.PresentNodePool(nodePool) + if presErr != nil { + return nil, errors.GeneralError("Failed to present nodepool: %v", presErr) + } + return presented, nil }, } diff --git a/pkg/handlers/nodepool_status.go b/pkg/handlers/nodepool_status.go index 8033db3..ce79d40 100644 --- a/pkg/handlers/nodepool_status.go +++ b/pkg/handlers/nodepool_status.go @@ -41,7 +41,11 @@ func (h nodePoolStatusHandler) List(w http.ResponseWriter, r *http.Request) { // Convert to OpenAPI models items := make([]openapi.AdapterStatus, 0, len(adapterStatuses)) for _, as := range adapterStatuses { - items = append(items, presenters.PresentAdapterStatus(as)) + presented, presErr := presenters.PresentAdapterStatus(as) + if presErr != nil { + return nil, errors.GeneralError("Failed to present adapter status: %v", presErr) + } + items = append(items, presented) } // Return list response with pagination metadata @@ -98,7 +102,10 @@ func (h nodePoolStatusHandler) Create(w http.ResponseWriter, r *http.Request) { log.Extra("nodepool_id", nodePoolID).Extra("error", aggregateErr).Warning("Failed to aggregate nodepool status") } - status := presenters.PresentAdapterStatus(adapterStatus) + status, presErr := presenters.PresentAdapterStatus(adapterStatus) + if presErr != nil { + return nil, errors.GeneralError("Failed to present adapter status: %v", presErr) + } return &status, nil }, handleError,