From 3faa138732df93d4fd9c4f33ad1d6fb7d60e2643 Mon Sep 17 00:00:00 2001 From: Tim Gross Date: Wed, 12 Aug 2020 15:59:10 -0400 Subject: [PATCH] fix panic converting structs to API in CSI endpoint (#8659) --- command/agent/csi_endpoint.go | 24 ++++++++++++++++++++++++ command/agent/csi_endpoint_test.go | 22 ++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/command/agent/csi_endpoint.go b/command/agent/csi_endpoint.go index 16734f7b6..72a7a2ebd 100644 --- a/command/agent/csi_endpoint.go +++ b/command/agent/csi_endpoint.go @@ -268,6 +268,9 @@ func (s *HTTPServer) CSIPluginSpecificRequest(resp http.ResponseWriter, req *htt // structsCSIPluginToApi converts CSIPlugin, setting Expected the count of known plugin // instances func structsCSIPluginToApi(plug *structs.CSIPlugin) *api.CSIPlugin { + if plug == nil { + return nil + } out := &api.CSIPlugin{ ID: plug.ID, Provider: plug.Provider, @@ -301,6 +304,9 @@ func structsCSIPluginToApi(plug *structs.CSIPlugin) *api.CSIPlugin { // structsCSIVolumeToApi converts CSIVolume, creating the allocation array func structsCSIVolumeToApi(vol *structs.CSIVolume) *api.CSIVolume { + if vol == nil { + return nil + } out := &api.CSIVolume{ ID: vol.ID, Name: vol.Name, @@ -344,6 +350,9 @@ func structsCSIVolumeToApi(vol *structs.CSIVolume) *api.CSIVolume { // structsCSIInfoToApi converts CSIInfo, part of CSIPlugin func structsCSIInfoToApi(info *structs.CSIInfo) *api.CSIInfo { + if info == nil { + return nil + } out := &api.CSIInfo{ PluginID: info.PluginID, Healthy: info.Healthy, @@ -380,6 +389,9 @@ func structsCSIInfoToApi(info *structs.CSIInfo) *api.CSIInfo { // structsAllocListStubToApi converts AllocListStub, for CSIPlugin func structsAllocListStubToApi(alloc *structs.AllocListStub) *api.AllocationListStub { + if alloc == nil { + return nil + } out := &api.AllocationListStub{ ID: alloc.ID, EvalID: alloc.EvalID, @@ -416,6 +428,9 @@ func structsAllocListStubToApi(alloc *structs.AllocListStub) *api.AllocationList // structsAllocDeploymentStatusToApi converts RescheduleTracker, part of AllocListStub func structsAllocDeploymentStatusToApi(ads *structs.AllocDeploymentStatus) *api.AllocDeploymentStatus { + if ads == nil { + return nil + } out := &api.AllocDeploymentStatus{ Healthy: ads.Healthy, Timestamp: ads.Timestamp, @@ -427,6 +442,9 @@ func structsAllocDeploymentStatusToApi(ads *structs.AllocDeploymentStatus) *api. // structsRescheduleTrackerToApi converts RescheduleTracker, part of AllocListStub func structsRescheduleTrackerToApi(rt *structs.RescheduleTracker) *api.RescheduleTracker { + if rt == nil { + return nil + } out := &api.RescheduleTracker{} for _, e := range rt.Events { @@ -442,6 +460,9 @@ func structsRescheduleTrackerToApi(rt *structs.RescheduleTracker) *api.Reschedul // structsTaskStateToApi converts TaskState, part of AllocListStub func structsTaskStateToApi(ts *structs.TaskState) *api.TaskState { + if ts == nil { + return nil + } out := &api.TaskState{ State: ts.State, Failed: ts.Failed, @@ -460,6 +481,9 @@ func structsTaskStateToApi(ts *structs.TaskState) *api.TaskState { // structsTaskEventToApi converts TaskEvents, part of AllocListStub func structsTaskEventToApi(te *structs.TaskEvent) *api.TaskEvent { + if te == nil { + return nil + } out := &api.TaskEvent{ Type: te.Type, Time: te.Time, diff --git a/command/agent/csi_endpoint_test.go b/command/agent/csi_endpoint_test.go index ef5262f89..5dc8ed5f6 100644 --- a/command/agent/csi_endpoint_test.go +++ b/command/agent/csi_endpoint_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/hashicorp/nomad/api" + "github.com/hashicorp/nomad/nomad/mock" "github.com/hashicorp/nomad/nomad/state" "github.com/hashicorp/nomad/nomad/structs" "github.com/kr/pretty" @@ -99,3 +100,24 @@ func TestHTTP_CSIEndpointVolume(t *testing.T) { require.Equal(t, 2, out.NodesHealthy) }) } + +// TestHTTP_CSIEndpoint_Cast is a smoke test for converting from structs to +// API structs +func TestHTTP_CSIEndpoint_Cast(t *testing.T) { + t.Parallel() + + plugin := mock.CSIPlugin() + plugin.Nodes["node1"] = &structs.CSIInfo{ + PluginID: plugin.ID, + AllocID: "alloc1", + NodeInfo: &structs.CSINodeInfo{ID: "instance-1", MaxVolumes: 3}, + } + apiPlugin := structsCSIPluginToApi(plugin) + require.Equal(t, + plugin.Nodes["node1"].NodeInfo.MaxVolumes, + apiPlugin.Nodes["node1"].NodeInfo.MaxVolumes) + + vol := mock.CSIVolume(plugin) + apiVol := structsCSIVolumeToApi(vol) + require.Equal(t, vol.MountOptions.MountFlags, apiVol.MountOptions.MountFlags) +}