Repository: kubernetes-sigs/gcp-compute-persistent-disk-csi-driver
Pull request #1516 (2023-11-18 00:24:56)

[release-1.11] Add error logging when error is encountered fetching a VolumeSnapshotContent source image
This is an automated cherry-pick of #1514

/assign pwschuurman

```release-note
Properly wrap error from GCE Images.Get() API call, to fix a potential nil-ptr dereference
```


Patch:
diff --git a/pkg/gce-cloud-provider/compute/fake-gce.go b/pkg/gce-cloud-provider/compute/fake-gce.go
index 9753279a..ced0d26e 100644
--- a/pkg/gce-cloud-provider/compute/fake-gce.go
+++ b/pkg/gce-cloud-provider/compute/fake-gce.go
@@ -17,6 +17,8 @@ package gcecloudprovider
 import (
 	"context"
 	"fmt"
+	"net/http"
+	"regexp"
 	"strings"
 
 	"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
@@ -39,6 +41,15 @@ const (
 	imageURITemplateGlobal    = "projects/%s/global/images/%s"    //{gce.projectID}/global/images/{image.Name}"
 )
 
+var (
+	// Snaphsot and Image Regex must comply with RFC1035
+	rfc1035Regex = regexp.MustCompile("^[a-z]([-a-z0-9]*[a-z0-9])?$")
+)
+
+func isRFC1035(value string) bool {
+	return rfc1035Regex.MatchString(strings.ToLower(value))
+}
+
 type FakeCloudProvider struct {
 	project string
 	zone    string
@@ -332,6 +343,9 @@ func (cloud *FakeCloudProvider) GetInstanceOrError(ctx context.Context, instance
 
 // Snapshot Methods
 func (cloud *FakeCloudProvider) GetSnapshot(ctx context.Context, project, snapshotName string) (*computev1.Snapshot, error) {
+	if !isRFC1035(snapshotName) {
+		return nil, fmt.Errorf("invalid snapshot name %v: %w", snapshotName, invalidError())
+	}
 	snapshot, ok := cloud.snapshots[snapshotName]
 	if !ok {
 		return nil, notFoundError()
@@ -410,6 +424,9 @@ func (cloud *FakeCloudProvider) ListImages(ctx context.Context, filter string) (
 }
 
 func (cloud *FakeCloudProvider) GetImage(ctx context.Context, project, imageName string) (*computev1.Image, error) {
+	if !isRFC1035(imageName) {
+		return nil, fmt.Errorf("invalid image name %v: %w", imageName, invalidError())
+	}
 	image, ok := cloud.images[imageName]
 	if !ok {
 		return nil, notFoundError()
@@ -567,6 +584,7 @@ func notFoundError() *googleapi.Error {
 
 func invalidError() *googleapi.Error {
 	return &googleapi.Error{
+		Code: http.StatusBadRequest,
 		Errors: []googleapi.ErrorItem{
 			{
 				Reason: "invalid",
diff --git a/pkg/gce-pd-csi-driver/controller.go b/pkg/gce-pd-csi-driver/controller.go
index 19c31161..38ba1009 100644
--- a/pkg/gce-pd-csi-driver/controller.go
+++ b/pkg/gce-pd-csi-driver/controller.go
@@ -1391,6 +1391,7 @@ func (gceCS *GCEControllerServer) getSnapshotByID(ctx context.Context, snapshotI
 				// return empty list if no snapshot is found
 				return &csi.ListSnapshotsResponse{}, nil
 			}
+			return nil, common.LoggedError("Failed to get image snapshot: ", err)
 		}
 		e, err := generateDiskImageEntry(image)
 		if err != nil {


Test patch:
diff --git a/pkg/gce-pd-csi-driver/controller_test.go b/pkg/gce-pd-csi-driver/controller_test.go
index d9e92ff8..8c5e611b 100644
--- a/pkg/gce-pd-csi-driver/controller_test.go
+++ b/pkg/gce-pd-csi-driver/controller_test.go
@@ -293,6 +293,15 @@ func TestListSnapshotsArguments(t *testing.T) {
 			numImages:     2,
 			expectedCount: 1,
 		},
+		{
+			name: "valid image",
+			req: &csi.ListSnapshotsRequest{
+				SnapshotId: testImageID + "0",
+			},
+			numSnapshots:  3,
+			numImages:     2,
+			expectedCount: 1,
+		},
 		{
 			name: "invalid id",
 			req: &csi.ListSnapshotsRequest{
@@ -300,6 +309,29 @@ func TestListSnapshotsArguments(t *testing.T) {
 			},
 			expectedCount: 0,
 		},
+		{
+			name: "invalid image id",
+			req: &csi.ListSnapshotsRequest{
+				SnapshotId: testImageID + "/foo",
+			},
+			expectedCount: 0,
+		},
+		{
+			name: "invalid snapshot name",
+			req: &csi.ListSnapshotsRequest{
+				SnapshotId: testSnapshotID + "-invalid-snapshot-",
+			},
+			expectedCount: 0,
+			expErrCode:    codes.InvalidArgument,
+		},
+		{
+			name: "invalid image name",
+			req: &csi.ListSnapshotsRequest{
+				SnapshotId: testImageID + "-invalid-image-",
+			},
+			expectedCount: 0,
+			expErrCode:    codes.InvalidArgument,
+		},
 		{
 			name: "no id",
 			req: &csi.ListSnapshotsRequest{