How to change storage class of single object in GCS bucket?

Viewed 492

I'm currently trying to write some code to transition some "regional" objects to "coldline" within a Google Storage bucket, but I'm getting the following exception:

{The service storage has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError Invalid argument [400] Errors [ Message[Invalid argument] Location[ - ] Reason[invalid] Domain[global] ]

at Google.Apis.Requests.ClientServiceRequest1.ParseResponse(HttpResponseMessage response) in C:\Apiary\support1351\Src\Support\Google.Apis\Requests\ClientServiceRequest.cs:line 192 at Google.Apis.Requests.ClientServiceRequest1.Execute() in C:\Apiary\support1351\Src\Support\Google.Apis\Requests\ClientServiceRequest.cs:line 116 at Example.Core.Google.GoogleStorageHandler.Archive() in C:\work\teams-api\Example\Example.Core.Google\GoogleStorageHandler.cs:line 365}

My code is as follows:

StorageClient _storageClient;

string storageBucket = "testBucket";
string storageKey = "testFile";

// Test object setup code (added for this question to make the sample more complete)
using (var stream = new MemoryStream(new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4 }))
{
    _storageClient.UploadObject(storageBucket, storageKey, null, stream);
}
// End of setup code

var objectData = _storageClient.GetObject(storageBucket, storageKey);
if (!string.Equals(objectData.StorageClass, "coldline", StringComparison.InvariantCultureIgnoreCase))
{
    objectData.StorageClass = "coldline";
    _storageClient.UpdateObject(objectData); // exception thrown here
}

I've confirmed that I can make other changes to the same object's metadata (by replacing objectData.StorageClass with objectData.ContentType, for example), but I can't change the storage class. The only issue I found that sounded related was this one, which resulted in the same error. Unfortunately, I'm using the fixed version of the SDK that Jon recommended (2.2.1), so it doesn't seem to be the same issue. I've also tried with the latest pre-release version (2.3.0-beta04) and I see no improvement.

I can change the object's StorageClass class via gsutil and this is reflected if I poll the object the object on the get object help page. If I try to patch it with the same storageClass, it works. If I try to change the storageClass, it fails and gives me the following 400 error:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "invalid",
    "message": "Invalid argument"
   }
  ],
  "code": 400,
  "message": "Invalid argument"
 }
}

Given that gsutil can change it, I'm inclined to believe I should be able to via the SDK or the API, but I can't. This page states that the storageClass field is writable. Am I missing some other data I need to include? There don't seem to be any useful overloads to UpdateObject which will affect my situation.

1 Answers

Based on this documentation, I don't think you can update the storage class directly with a patch or update. Instead, you need to perform a rewrite operation on the object.

We don't currently expose rewrites directly in Google.Cloud.Storage.V1, but you should be able to use the underlying service:

var obj = new Google.Apis.Storage.v1.Data.Object { StorageClass = "coldline" };
client.Service.Objects.Rewrite(obj, bucketName, objectName, bucketName, objectName).Execute();
Related