Repository: kubernetes-sigs/gcp-filestore-csi-driver
Pull request #249 (2022-04-08 19:33:22)

fix error code mappings
**What type of PR is this?**
Follow up to #206 which had an invalid http mapping. It checked that the grpc code was in the map, not that the http error code is in the map (which is what the googleapi error has in code.  Also had to remove the error wrapping from the CreateInstance and CreateInstanceFromBackupSource functions so that casting to googleapi error is not nil. 

/kind cleanup


**Does this PR introduce a user-facing change?**:
<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".
-->
```release-note
returns InvalidArgument instead of Internal error code for some common user errors which is visible to users with a kubectl describe command 
```


k8s-ci-robot: @amacaskill: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our [release note process](https://git.k8s.io/community/contributors/guide/release-notes.md) to remove it.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/gcp-filestore-csi-driver/pull/249#" title="Author self-approved">amacaskill</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **saad-ali** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @saad-ali` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fgcp-filestore-csi-driver).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes-sigs/gcp-filestore-csi-driver/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["saad-ali"]} -->
amacaskill: Manually tested error 400 : 
```GRPC error: rpc error: code = InvalidArgument desc = googleapi: Error 400: network 'djakefault' does not exist., badRequest
```
```GRPC error: rpc error: code = InvalidArgument desc = googleapi: Error 400: capacity must be at least 2560 GB., badRequest
```

Wasn't able to test 403 or 429 still trying to test 404 for Create snapshot. 
leiyiz: Yeah that makes sense, if we can't easily reproduce it, it's probably good to remove it as a user error
leiyiz: /lgtm
k8s-ci-robot: New changes are detected. LGTM label has been removed.
k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/gcp-filestore-csi-driver/pull/249#" title="Author self-approved">amacaskill</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please ask for approval from **leiyiz** after the PR has been reviewed.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fgcp-filestore-csi-driver).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes-sigs/gcp-filestore-csi-driver/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["leiyiz"]} -->
leiyiz: /lgtm
k8s-ci-robot: New changes are detected. LGTM label has been removed.
k8s-ci-robot: @amacaskill: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-gcp-filestore-csi-driver-e2e | 9f7de0995a0ee828d84e2317b853230a3a7ee2a7 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/sigs.k8s.io_gcp-filestore-csi-driver/249/pull-gcp-filestore-csi-driver-e2e/1516527366107566080/) | true | `/test pull-gcp-filestore-csi-driver-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=gcp-filestore-csi-driver&pr=249). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Aamacaskill). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/gcp-filestore-csi-driver/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
amacaskill:   also  manually tested 403 error: 
```
Warning  ProvisioningFailed    12s (x5 over 27s)  filestore.csi.storage.gke.io_gke-7f715c2c9f5d4c938326-7586-15c5-vm_29746fe9-8b54-4a5a-81f0-0e650c2dd156  failed to provision volume with StorageClass "filestore-example": rpc error: code = InvalidArgument desc = googleapi: Error 403: Cloud Filestore API has not been used in project 876590250267 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/file.googleapis.com/overview?project=876590250267 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
```

k8s-ci-robot: @amacaskill: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-gcp-filestore-csi-driver-e2e | 198bac8016edcbcdfeb7bc8f8b69126b8cb95a26 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/sigs.k8s.io_gcp-filestore-csi-driver/249/pull-gcp-filestore-csi-driver-e2e/1516899125646331904/) | true | `/test pull-gcp-filestore-csi-driver-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=gcp-filestore-csi-driver&pr=249). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Aamacaskill). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/gcp-filestore-csi-driver/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @amacaskill: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-gcp-filestore-csi-driver-e2e | 01939e2dc110363cf21bdc642d7ed1572dc75b7f | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/sigs.k8s.io_gcp-filestore-csi-driver/249/pull-gcp-filestore-csi-driver-e2e/1516902206723330048/) | true | `/test pull-gcp-filestore-csi-driver-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=gcp-filestore-csi-driver&pr=249). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Aamacaskill). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/gcp-filestore-csi-driver/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
amacaskill: /retest
k8s-ci-robot: @amacaskill: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-gcp-filestore-csi-driver-e2e | 01939e2dc110363cf21bdc642d7ed1572dc75b7f | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/sigs.k8s.io_gcp-filestore-csi-driver/249/pull-gcp-filestore-csi-driver-e2e/1516913229391990784/) | true | `/test pull-gcp-filestore-csi-driver-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=gcp-filestore-csi-driver&pr=249). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Aamacaskill). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/gcp-filestore-csi-driver/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
amacaskill: /retest

k8s-ci-robot: @amacaskill: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-gcp-filestore-csi-driver-e2e | 01939e2dc110363cf21bdc642d7ed1572dc75b7f | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/sigs.k8s.io_gcp-filestore-csi-driver/249/pull-gcp-filestore-csi-driver-e2e/1516917805818056704/) | true | `/test pull-gcp-filestore-csi-driver-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=gcp-filestore-csi-driver&pr=249). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Aamacaskill). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/gcp-filestore-csi-driver/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/cmd/main.go b/cmd/main.go
index 79c497fd..8cd1d8f4 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -33,16 +33,14 @@ import (
 )
 
 var (
-	endpoint                = flag.String("endpoint", "unix:/tmp/csi.sock", "CSI endpoint")
-	nodeID                  = flag.String("nodeid", "", "node id")
-	runController           = flag.Bool("controller", false, "run controller service")
-	runNode                 = flag.Bool("node", false, "run node service")
-	cloudConfigFilePath     = flag.String("cloud-config", "", "Path to GCE cloud provider config")
-	httpEndpoint            = flag.String("http-endpoint", "", "The TCP network address where the prometheus metrics endpoint will listen (example: `:8080`). The default is empty string, which means metrics endpoint is disabled.")
-	metricsPath             = flag.String("metrics-path", "/metrics", "The HTTP path where prometheus metrics will be exposed. Default is `/metrics`.")
-	enableMultishare        = flag.Bool("enable-multishare", false, "if set to true, the driver will support multishare instance provisioning")
-	filestoreServiceEnpoint = flag.String("filestore-service-endpoint", "", "Endpoint for filestore service")
-	ecfsDescription         = flag.String("ecfs-description", "", "Filestore multishare instance descrption. ecfs-version=<version>,image-project-id=<projectid>")
+	endpoint            = flag.String("endpoint", "unix:/tmp/csi.sock", "CSI endpoint")
+	nodeID              = flag.String("nodeid", "", "node id")
+	runController       = flag.Bool("controller", false, "run controller service")
+	runNode             = flag.Bool("node", false, "run node service")
+	cloudConfigFilePath = flag.String("cloud-config", "", "Path to GCE cloud provider config")
+	httpEndpoint        = flag.String("http-endpoint", "", "The TCP network address where the prometheus metrics endpoint will listen (example: `:8080`). The default is empty string, which means metrics endpoint is disabled.")
+	metricsPath         = flag.String("metrics-path", "/metrics", "The HTTP path where prometheus metrics will be exposed. Default is `/metrics`.")
+	enableMultishare    = flag.Bool("enable-multishare", false, "if set to true, the driver will support multishare instance provisioning")
 	// This is set at compile time
 	version = "unknown"
 )
@@ -60,13 +58,16 @@ func main() {
 	var meta metadata.Service
 	var mm *metrics.MetricsManager
 	if *runController {
+		if *enableMultishare {
+			klog.Fatalf("provisioning of multishare instances not supported")
+		}
 		if *httpEndpoint != "" && metrics.IsGKEComponentVersionAvailable() {
 			mm = metrics.NewMetricsManager()
 			mm.InitializeHttpHandler(*httpEndpoint, *metricsPath)
 			mm.EmitGKEComponentVersion()
 		}
 
-		provider, err = cloud.NewCloud(ctx, version, *cloudConfigFilePath, *filestoreServiceEnpoint)
+		provider, err = cloud.NewCloud(ctx, version, *cloudConfigFilePath)
 	} else {
 		if *nodeID == "" {
 			klog.Fatalf("nodeid cannot be empty for node service")
@@ -94,7 +95,6 @@ func main() {
 		MetadataService:  meta,
 		EnableMultishare: *enableMultishare,
 		Metrics:          mm,
-		EcfsDescription:  *ecfsDescription,
 	}
 
 	gcfsDriver, err := driver.NewGCFSDriver(config)
diff --git a/pkg/cloud_provider/cloud.go b/pkg/cloud_provider/cloud.go
index ce22136c..3b5a8a44 100644
--- a/pkg/cloud_provider/cloud.go
+++ b/pkg/cloud_provider/cloud.go
@@ -51,7 +51,7 @@ type ConfigGlobal struct {
 	Zone      string `gcfg:"zone"`
 }
 
-func NewCloud(ctx context.Context, version string, configPath string, filestoreServiceEndpoint string) (*Cloud, error) {
+func NewCloud(ctx context.Context, version string, configPath string) (*Cloud, error) {
 	configFile, err := maybeReadConfig(configPath)
 	if err != nil {
 		return nil, err
@@ -67,7 +67,7 @@ func NewCloud(ctx context.Context, version string, configPath string, filestoreS
 		return nil, err
 	}
 
-	file, err := file.NewGCFSService(version, client, filestoreServiceEndpoint)
+	file, err := file.NewGCFSService(version, client)
 	if err != nil {
 		return nil, fmt.Errorf("failed to initialize Filestore service: %v", err)
 	}
diff --git a/pkg/cloud_provider/file/file.go b/pkg/cloud_provider/file/file.go
index 473d8f5f..520bc5c6 100644
--- a/pkg/cloud_provider/file/file.go
+++ b/pkg/cloud_provider/file/file.go
@@ -29,7 +29,6 @@ import (
 	"github.com/golang/glog"
 	"google.golang.org/api/googleapi"
 	"google.golang.org/api/option"
-	"google.golang.org/genproto/googleapis/rpc/code"
 	"k8s.io/apimachinery/pkg/util/wait"
 	"k8s.io/klog"
 	"sigs.k8s.io/gcp-filestore-csi-driver/pkg/util"
@@ -64,7 +63,6 @@ type MultishareInstance struct {
 	Labels             map[string]string
 	State              string
 	KmsKeyName         string
-	Description        string
 }
 
 type ListFilter struct {
@@ -154,7 +152,7 @@ const (
 
 var _ Service = &gcfsServiceManager{}
 
-func NewGCFSService(version string, client *http.Client, endpoint string) (Service, error) {
+func NewGCFSService(version string, client *http.Client) (Service, error) {
 	ctx := context.Background()
 	fileService, err := filev1beta1.NewService(ctx, option.WithHTTPClient(client))
 	if err != nil {
@@ -162,9 +160,7 @@ func NewGCFSService(version string, client *http.Client, endpoint string) (Servi
 	}
 	fileService.UserAgent = fmt.Sprintf("Google Cloud Filestore CSI Driver/%s (%s %s)", version, runtime.GOOS, runtime.GOARCH)
 
-	basepath := createFilestoreEndpointUrlBasePath(endpoint)
-	glog.Infof("Using endpoint %s for multshare", createFilestoreEndpointUrlBasePath(endpoint))
-	fileMultishareService, err := filev1beta1multishare.NewService(ctx, basepath, option.WithHTTPClient(client))
+	fileMultishareService, err := filev1beta1multishare.NewService(ctx, option.WithHTTPClient(client))
 	if err != nil {
 		return nil, err
 	}
@@ -215,17 +211,20 @@ func (manager *gcfsServiceManager) CreateInstance(ctx context.Context, obj *Serv
 		betaObj.Labels)
 	op, err := manager.instancesService.Create(locationURI(obj.Project, obj.Location), betaObj).InstanceId(obj.Name).Context(ctx).Do()
 	if err != nil {
-		return nil, fmt.Errorf("CreateInstance operation failed: %v", err)
+		glog.Errorf("CreateInstance operation failed for instance %s: %v", obj.Name, err)
+		return nil, err
 	}
 
 	glog.V(4).Infof("For instance %v, waiting for create instance op %v to complete", obj.Name, op.Name)
 	err = manager.waitForOp(ctx, op)
 	if err != nil {
-		return nil, fmt.Errorf("WaitFor CreateInstance op %s failed: %v", op.Name, err)
+		glog.Errorf("WaitFor CreateInstance op %s failed: %v", op.Name, err)
+		return nil, err
 	}
 	instance, err := manager.GetInstance(ctx, obj)
 	if err != nil {
-		return nil, fmt.Errorf("failed to get instance after creation: %v", err)
+		glog.Errorf("failed to get instance after creation: %v", err)
+		return nil, err
 	}
 	return instance, nil
 }
@@ -266,17 +265,20 @@ func (manager *gcfsServiceManager) CreateInstanceFromBackupSource(ctx context.Co
 		instance.FileShares[0].SourceBackup)
 	op, err := manager.instancesService.Create(locationURI(obj.Project, obj.Location), instance).InstanceId(obj.Name).Context(ctx).Do()
 	if err != nil {
-		return nil, fmt.Errorf("CreateInstance operation failed: %v", err)
+		glog.Errorf("CreateInstance operation failed for instance %v: %v", obj.Name, err)
+		return nil, err
 	}
 
 	glog.V(4).Infof("For instance %v, waiting for create instance op %v to complete", obj.Name, op.Name)
 	err = manager.waitForOp(ctx, op)
 	if err != nil {
-		return nil, fmt.Errorf("WaitFor CreateInstance op %s failed: %v", op.Name, err)
+		glog.Errorf("WaitFor CreateInstance op %s failed: %v", op.Name, err)
+		return nil, err
 	}
 	serviceInstance, err := manager.GetInstance(ctx, obj)
 	if err != nil {
-		return nil, fmt.Errorf("failed to get instance after creation: %v", err)
+		glog.Errorf("failed to get instance after creation: %v", err)
+		return nil, err
 	}
 	return serviceInstance, nil
 }
@@ -477,7 +479,8 @@ func (manager *gcfsServiceManager) CreateBackup(ctx context.Context, obj *Servic
 	glog.V(4).Infof("Creating backup object %+v for the URI %v", *backupobj, backupUri)
 	opbackup, err := manager.backupService.Create(locationURI(obj.Project, region), backupobj).BackupId(backupName).Context(ctx).Do()
 	if err != nil {
-		return nil, fmt.Errorf("Create Backup operation failed: %v", err)
+		glog.Errorf("Create Backup operation failed: %v", err)
+		return nil, err
 	}
 
 	glog.V(4).Infof("For backup uri %s, waiting for backup op %v to complete", backupUri, opbackup.Name)
@@ -586,21 +589,26 @@ func IsNotFoundErr(err error) bool {
 	return false
 }
 
-// This function returns true if the error is a googleapi error caused by users, such as
-// Error 429: Quota limit exceeded, Error 403: Permission Denied, Error 400: Bad Request,
-// Error 404: Not found.
+// IsUserError returns true if the error is a googleapi.Error with
+// Error 403: Permission Denied, Error 400: Bad Request
 func IsUserError(err error) bool {
-	apiErr, ok := err.(*googleapi.Error)
-	if !ok {
-		return false
+	userErrors := map[int]bool{
+		http.StatusForbidden:  true,
+		http.StatusBadRequest: true,
 	}
-	userErrors := map[code.Code]bool{
-		code.Code_RESOURCE_EXHAUSTED: true,
-		code.Code_PERMISSION_DENIED:  true,
-		code.Code_INVALID_ARGUMENT:   true,
-		code.Code_NOT_FOUND:          true,
+	if apiErr, ok := err.(*googleapi.Error); ok && userErrors[apiErr.Code] {
+		return true
 	}
-	return userErrors[code.Code(apiErr.Code)]
+	return false
+}
+
+// IsTooManyRequestError returns true if the error is a googleapi.Error with
+// Error 429: Status Too Many Requests.
+func IsTooManyRequestError(err error) bool {
+	if apierr, ok := err.(*googleapi.Error); ok && apierr.Code == http.StatusTooManyRequests {
+		return true
+	}
+	return false
 }
 
 // This function returns the backup URI, the region that was picked to be the backup resource location and error.
@@ -705,8 +713,7 @@ func (manager *gcfsServiceManager) ListMultishareInstances(ctx context.Context,
 
 func (manager *gcfsServiceManager) StartCreateMultishareInstanceOp(ctx context.Context, instance *MultishareInstance) (*filev1beta1multishare.Operation, error) {
 	targetinstance := &filev1beta1multishare.Instance{
-		MultiShareEnabled: true,
-		Tier:              instance.Tier,
+		Tier: instance.Tier,
 		Networks: []*filev1beta1multishare.NetworkConfig{
 			{
 				Network:         instance.Network.Name,
@@ -715,10 +722,9 @@ func (manager *gcfsServiceManager) StartCreateMultishareInstanceOp(ctx context.C
 				ConnectMode:     instance.Network.ConnectMode,
 			},
 		},
-		CapacityGb:  util.BytesToGb(instance.CapacityBytes),
-		KmsKeyName:  instance.KmsKeyName,
-		Labels:      instance.Labels,
-		Description: instance.Description,
+		CapacityGb: util.BytesToGb(instance.CapacityBytes),
+		KmsKeyName: instance.KmsKeyName,
+		Labels:     instance.Labels,
 	}
 
 	klog.V(4).Infof("Creating instance %q: project %q, location %q, tier %q, capacity %v, network %q, ipRange %q, connectMode %q, KmsKeyName %q, labels %v", instance.Name, instance.Project, instance.Location, targetinstance.Tier, targetinstance.CapacityGb, targetinstance.Networks[0].Network, targetinstance.Networks[0].ReservedIpRange, targetinstance.Networks[0].ConnectMode, targetinstance.KmsKeyName, targetinstance.Labels)
@@ -900,14 +906,9 @@ func cloudInstanceToMultishareInstance(instance *filev1beta1multishare.Instance)
 		CapacityBytes:      instance.CapacityGb * util.Gb,
 		MaxCapacityBytes:   instance.MaxCapacityGb * util.Gb,
 		CapacityStepSizeGb: instance.CapacityStepSizeGb,
-		Description:        instance.Description,
 	}, nil
 }
 
 func shareURI(project, location, instanceName, shareName string) string {
 	return fmt.Sprintf(shareURIFmt, project, location, instanceName, shareName)
 }
-
-func createFilestoreEndpointUrlBasePath(endpoint string) string {
-	return "https://" + endpoint + "/"
-}
diff --git a/pkg/csi_driver/controller.go b/pkg/csi_driver/controller.go
index 24f1c42a..5718dfa0 100644
--- a/pkg/csi_driver/controller.go
+++ b/pkg/csi_driver/controller.go
@@ -96,13 +96,12 @@ type controllerServerConfig struct {
 	enableMultishare     bool
 	multiShareController *MultishareController
 	metricsManager       *metrics.MetricsManager
-	ecfsDescription      string
 }
 
 func newControllerServer(config *controllerServerConfig) csi.ControllerServer {
 	config.ipAllocator = util.NewIPAllocator(make(map[string]bool))
 	if config.enableMultishare {
-		config.multiShareController = NewMultishareController(config.driver, config.fileService, config.cloud, config.volumeLocks, config.ecfsDescription)
+		config.multiShareController = NewMultishareController(config.driver, config.fileService, config.cloud, config.volumeLocks)
 	}
 	return &controllerServer{config: config}
 }
@@ -110,9 +109,6 @@ func newControllerServer(config *controllerServerConfig) csi.ControllerServer {
 // CreateVolume creates a GCFS instance
 func (s *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
 	if strings.ToLower(req.GetParameters()[paramMultishare]) == "true" {
-		if s.config.multiShareController == nil {
-			return nil, status.Error(codes.InvalidArgument, "multishare controller not enabled")
-		}
 		start := time.Now()
 		response, err := s.config.multiShareController.CreateVolume(ctx, req)
 		duration := time.Since(start)
@@ -177,8 +173,13 @@ func (s *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolu
 
 	// Check if the instance already exists
 	filer, err := s.config.fileService.GetInstance(ctx, newFiler)
-	if err != nil && !file.IsNotFoundErr(err) {
-		return nil, status.Error(codes.Internal, err.Error())
+	if err != nil {
+		if file.IsUserError(err) {
+			return nil, status.Error(codes.InvalidArgument, err.Error())
+		}
+		if !file.IsNotFoundErr(err) {
+			return nil, status.Error(codes.Internal, err.Error())
+		}
 	}
 
 	if filer != nil {
@@ -239,6 +240,8 @@ func (s *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolu
 			glog.Errorf("Create volume for volume Id %s failed: %v", volumeID, createErr)
 			if file.IsUserError(createErr) {
 				return nil, status.Error(codes.InvalidArgument, createErr.Error())
+			} else if file.IsTooManyRequestError(createErr) {
+				return nil, status.Error(codes.ResourceExhausted, createErr.Error())
 			} else {
 				return nil, status.Error(codes.Internal, createErr.Error())
 			}
@@ -289,9 +292,6 @@ func (s *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVolu
 	}
 
 	if isMultishareVolId(volumeID) {
-		if s.config.multiShareController == nil {
-			return nil, status.Error(codes.InvalidArgument, "multishare controller not enabled")
-		}
 		start := time.Now()
 		response, err := s.config.multiShareController.DeleteVolume(ctx, req)
 		duration := time.Since(start)
@@ -743,7 +743,7 @@ func (s *controllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateSn
 	backupObj, err := s.config.fileService.CreateBackup(ctx, filer, req.Name, util.GetBackupLocation(req.GetParameters()))
 	if err != nil {
 		glog.Errorf("Create snapshot for volume Id %s failed: %v", volumeID, err)
-		if file.IsUserError(err) {
+		if file.IsNotFoundErr(err) {
 			return nil, status.Error(codes.InvalidArgument, err.Error())
 		} else {
 			return nil, status.Error(codes.Internal, err.Error())
diff --git a/pkg/csi_driver/gcfs_driver.go b/pkg/csi_driver/gcfs_driver.go
index 70707253..081d7a2b 100644
--- a/pkg/csi_driver/gcfs_driver.go
+++ b/pkg/csi_driver/gcfs_driver.go
@@ -41,7 +41,6 @@ type GCFSDriverConfig struct {
 	MetadataService  metadataservice.Service
 	EnableMultishare bool
 	Metrics          *metrics.MetricsManager
-	EcfsDescription  string
 }
 
 type GCFSDriver struct {
@@ -108,7 +107,6 @@ func NewGCFSDriver(config *GCFSDriverConfig) (*GCFSDriver, error) {
 			volumeLocks:      util.NewVolumeLocks(),
 			enableMultishare: config.EnableMultishare,
 			metricsManager:   config.Metrics,
-			ecfsDescription:  config.EcfsDescription,
 		})
 	}
 
diff --git a/pkg/csi_driver/multishare_controller.go b/pkg/csi_driver/multishare_controller.go
index 85524f40..f8e1b8be 100644
--- a/pkg/csi_driver/multishare_controller.go
+++ b/pkg/csi_driver/multishare_controller.go
@@ -25,7 +25,6 @@ import (
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 	"k8s.io/apimachinery/pkg/util/uuid"
-	"k8s.io/klog"
 	cloud "sigs.k8s.io/gcp-filestore-csi-driver/pkg/cloud_provider"
 	"sigs.k8s.io/gcp-filestore-csi-driver/pkg/cloud_provider/file"
 	"sigs.k8s.io/gcp-filestore-csi-driver/pkg/util"
@@ -34,29 +33,26 @@ import (
 const (
 	modeMultishare = "modeMultishare"
 
-	methodCreateVolume         = "CreateVolume"
-	methodDeleteVolume         = "DeleteVolume"
-	ecfsDataPlaneVersionFormat = "GoogleReserved-CustomVMImage=clh.image.ems.path:projects/%s/global/images/ems-filestore-scaleout-%s"
+	methodCreateVolume = "CreateVolume"
+	methodDeleteVolume = "DeleteVolume"
 )
 
 // MultishareController handles CSI calls for volumes which use Filestore multishare instances.
 type MultishareController struct {
-	driver          *GCFSDriver
-	fileService     file.Service
-	cloud           *cloud.Cloud
-	opsManager      *MultishareOpsManager
-	volumeLocks     *util.VolumeLocks
-	ecfsDescription string
+	driver      *GCFSDriver
+	fileService file.Service
+	cloud       *cloud.Cloud
+	opsManager  *MultishareOpsManager
+	volumeLocks *util.VolumeLocks
 }
 
-func NewMultishareController(driver *GCFSDriver, fileService file.Service, cloud *cloud.Cloud, volumeLock *util.VolumeLocks, ecfsDescription string) *MultishareController {
+func NewMultishareController(driver *GCFSDriver, fileService file.Service, cloud *cloud.Cloud, volumeLock *util.VolumeLocks) *MultishareController {
 	return &MultishareController{
-		opsManager:      NewMultishareOpsManager(cloud),
-		driver:          driver,
-		fileService:     fileService,
-		cloud:           cloud,
-		volumeLocks:     volumeLock,
-		ecfsDescription: ecfsDescription,
+		opsManager:  NewMultishareOpsManager(cloud),
+		driver:      driver,
+		fileService: fileService,
+		cloud:       cloud,
+		volumeLocks: volumeLock,
 	}
 }
 
@@ -207,7 +203,7 @@ func (m *MultishareController) ControllerExpandVolume(ctx context.Context, req *
 func getInstanceSCPrefix(req *csi.CreateVolumeRequest) (string, error) {
 	params := req.GetParameters()
 	v, ok := params[paramMultishareInstanceScLabel]
-	if !ok {
+	if ok {
 		return "", fmt.Errorf("Failed to find instance prefix key")
 	}
 
@@ -248,7 +244,7 @@ func (m *MultishareController) generateNewMultishareInstance(instanceName string
 			continue
 		case paramMultishareInstanceScLabel:
 			continue
-		case ParameterKeyLabels, ParameterKeyPVCName, ParameterKeyPVCNamespace, ParameterKeyPVName, paramMultishare:
+		case ParameterKeyLabels, ParameterKeyPVCName, ParameterKeyPVCNamespace, ParameterKeyPVName:
 		case "csiprovisionersecretname", "csiprovisionersecretnamespace":
 		default:
 			return nil, status.Errorf(codes.InvalidArgument, fmt.Sprintf("invalid parameter %q", k))
@@ -274,9 +270,8 @@ func (m *MultishareController) generateNewMultishareInstance(instanceName string
 			Name:        network,
 			ConnectMode: connectMode,
 		},
-		KmsKeyName:  kmsKeyName,
-		Labels:      labels,
-		Description: generateInstanceDescFromEcfsDesc(m.ecfsDescription),
+		KmsKeyName: kmsKeyName,
+		Labels:     labels,
 	}, nil
 }
 
@@ -428,44 +423,3 @@ func containsInstancePrefix(shareHandle string, project, location, instanceName
 	targetInstance := fmt.Sprintf("%s/%s/%s", project, location, instanceName)
 	return strings.Contains(shareHandle, targetInstance)
 }
-
-func generateInstanceDescFromEcfsDesc(desc string) string {
-	if desc == "" {
-		return desc
-	}
-
-	parts := strings.Split(desc, ",")
-	descMap := make(map[string]string)
-	for _, part := range parts {
-		pair := strings.Split(part, "=")
-		if len(pair) != 2 {
-			continue
-		}
-		descMap[pair[0]] = pair[1]
-	}
-
-	const (
-		ecfsVersionKey    = "ecfs-version"
-		imageProjectIdKey = "image-project-id"
-	)
-	var (
-		ecfsVersion    string
-		imageProjectId string
-	)
-	for k, v := range descMap {
-		switch k {
-		case ecfsVersionKey:
-			ecfsVersion = v
-		case imageProjectIdKey:
-			imageProjectId = v
-		}
-	}
-
-	if ecfsVersion == "" || imageProjectId == "" {
-		return ""
-	}
-
-	d := fmt.Sprintf(ecfsDataPlaneVersionFormat, imageProjectId, ecfsVersion)
-	klog.V(4).Infof("generated description for multishare instance %s", d)
-	return d
-}
diff --git a/vendor/google.golang.org/api/file/v1beta1multishare/file-gen.go b/vendor/google.golang.org/api/file/v1beta1multishare/file-gen.go
index 9e595561..65c74092 100755
--- a/vendor/google.golang.org/api/file/v1beta1multishare/file-gen.go
+++ b/vendor/google.golang.org/api/file/v1beta1multishare/file-gen.go
@@ -85,17 +85,13 @@ const (
 )
 
 // NewService creates a new Service.
-func NewService(ctx context.Context, base string, opts ...option.ClientOption) (*Service, error) {
+func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) {
 	scopesOption := option.WithScopes(
 		"https://www.googleapis.com/auth/cloud-platform",
 	)
 	// NOTE: prepend, so we don't override user-specified scopes.
 	opts = append([]option.ClientOption{scopesOption}, opts...)
-	if base != "" {
-		opts = append(opts, internaloption.WithDefaultEndpoint(base))
-	} else {
-		opts = append(opts, internaloption.WithDefaultEndpoint(basePath))
-	}
+	opts = append(opts, internaloption.WithDefaultEndpoint(basePath))
 	opts = append(opts, internaloption.WithDefaultMTLSEndpoint(mtlsBasePath))
 	client, endpoint, err := htransport.NewClient(ctx, opts...)
 	if err != nil {


Test patch:
diff --git a/pkg/csi_driver/multishare_controller_test.go b/pkg/csi_driver/multishare_controller_test.go
index 3d0b521a..7d49527a 100644
--- a/pkg/csi_driver/multishare_controller_test.go
+++ b/pkg/csi_driver/multishare_controller_test.go
@@ -17,7 +17,6 @@ limitations under the License.
 package driver
 
 import (
-	"fmt"
 	"reflect"
 	"testing"
 
@@ -45,7 +44,7 @@ func initTestMultishareController(t *testing.T) *MultishareController {
 	if err != nil {
 		t.Fatalf("Failed to get cloud provider: %v", err)
 	}
-	return NewMultishareController(initTestDriver(t), fileService, cloudProvider, util.NewVolumeLocks(), "")
+	return NewMultishareController(initTestDriver(t), fileService, cloudProvider, util.NewVolumeLocks())
 }
 
 func TestPickRegion(t *testing.T) {
@@ -534,49 +533,3 @@ func TestGenerateCSICreateVolumeResponse(t *testing.T) {
 		})
 	}
 }
-
-func TestGenerateInstanceDescFromEcfsDesc(t *testing.T) {
-	tests := []struct {
-		name       string
-		inputdesc  string
-		outputdesc string
-	}{
-		{
-			name: "empty",
-		},
-		{
-			name:      "invalid key value pair, unknown key",
-			inputdesc: "k1=v1",
-		},
-		{
-			name:      "invalid key value pair, unknown key1",
-			inputdesc: "k1=v1,ecfs-version=test",
-		},
-		{
-			name:      "invalid key value pair, unknown key2",
-			inputdesc: "k1=v1,image-project-id=test",
-		},
-		{
-			name:      "invalid key value pair",
-			inputdesc: "k1=v1,image-project-id",
-		},
-		{
-			name:       "case1: valid key value pair",
-			inputdesc:  "ecfs-version=ems-filestore-scaleout-3-6-0-1-70bd79ed0a91,image-project-id=elastifile-ci",
-			outputdesc: fmt.Sprintf(ecfsDataPlaneVersionFormat, "elastifile-ci", "ems-filestore-scaleout-3-6-0-1-70bd79ed0a91"),
-		},
-		{
-			name:       "case2: valid key value pair",
-			inputdesc:  "image-project-id=elastifile-ci,ecfs-version=ems-filestore-scaleout-3-6-0-1-70bd79ed0a91",
-			outputdesc: fmt.Sprintf(ecfsDataPlaneVersionFormat, "elastifile-ci", "ems-filestore-scaleout-3-6-0-1-70bd79ed0a91"),
-		},
-	}
-	for _, tc := range tests {
-		t.Run(tc.name, func(t *testing.T) {
-			op := generateInstanceDescFromEcfsDesc(tc.inputdesc)
-			if op != tc.outputdesc {
-				t.Errorf("got %s, want %s", op, tc.outputdesc)
-			}
-		})
-	}
-}