Paws the VI (Pardon my Error)

Now things are going good so far but I have run into a little snag with the program that is using my S3 RestoreObject code with Paws. Namely at this point my end user is trying to make the same restore request before the first restore has finished.

Right now if I capture the error with an eval {} in my call I get in the @$ is 'Conflict';

The API documentation does state that I can get as few special errors that are interesting to me;


+---------------------------------------+-------------------------------+--------+
| Message                               | Remarks                       | Status |
+---------------------------------------+-------------------------------+--------+
| RestoreAlreadyInProgress              | Object restore is already in  |   409  |
|                                       | progress. (This error does    |        |
|                                       | not apply to SELECT type      |        |
|                                       | requests.)                    |        |
|                                       |                               |        |
+---------------------------------------+-------------------------------+--------+ 
| GlacierExpeditedRetrievalNotAvailable | Glacier expedited retrievals  |   503  |
|                                       | are currently not available.  |        |
|                                       | Try again later. (Returned    |        |
|                                       | if there is insufficient      |        |
|                                       | capacity to process the       |        |
|                                       | Expedited request. This error |        |
|                                       | applies only to Expedited     |        |
|                                       | retrievals and not to         |        |
|                                       | Standard or Bulk retrievals.) |        |
+---------------------------------------+-------------------------------+--------+

As I have already dumped the response object and I get


bless( {
                 'content' => '<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>RestoreAlreadyInProgress</Code><Message>Object restore is already in progress</Message><RequestId>AC65B3BF8AC3AA34</RequestId><HostId>1Wlw6Edlx3uplC85VIcAwe12xfU8BgcaFHXTlyNBhilk4Xv2sbOJs80FjvAvW9weQkwtKJXcnJg=</HostId></Error>',
                 'status' => '409',
                 'headers' => {
                                'x-amz-id-2' => '1Wlw6Edlx3uplC85VIcAwe12xfU8BgcaFHXTlyNBhilk4Xv2sbOJs80FjvAvW9weQkwtKJXcnJg=',
                                'server' => 'AmazonS3',
                                'x-amz-request-id' => 'AC65B3BF8AC3AA34',
                                'content-type' => 'application/xml',
                                'date' => 'Wed, 25 Sep 2019 21:04:17 GMT',
                                'transfer-encoding' => 'chunked'
                              }
               }, 'Paws::Net::APIResponse' );

So for me getting that 409 error back as an object would be very useful for me, but how to get the error in a Paws object?

Well lets start with a test. I had a poke about the t/10_response dir looking for likely cadidates to copy form and right way I found 's3-create-bucket.1.response' and its test s3-create-bucket.1.response.test.yml

So another quick copy to get

s3-restore-object.3.response s3-restore-object.3.response.test.yml

and then I make some changes to s3-restore-object.3.response.test.yml


---
call: RestoreObject
service: S3
tests:
  - path: request_id
    op: eq
    expected:  AC65B3BF8AC3AA34
  - path: message
    op: eq
    expected:  Object restore is already in progress
  - path: code
    op: eq
    expected: 409

taking the values from the response object from above.

Now for the test values from the above response and use them to clean up the new file to look like this


---
content: |-
  <?xml version="1.0" encoding="UTF-8"?>
  <Error>
      <Code>RestoreAlreadyInProgress</Code>
      <Message>Object restore is already in progress</Message>
      <RequestId>AC65B3BF8AC3AA34</RequestId>
    <HostId>1Wlw6Edlx3uplC85VIcAwe12xfU8BgcaFHXTlyNBhilk4Xv2sbOJs80FjvAvW9weQkwtKJXcnJg=</HostId>
   </Error>
headers:
  connection: close
  content-type: application/xml
  date: 'Wed, 25 Sep 2019 21:04:17 GMT'
  server: AmazonS3
  transfer-encoding: chunked
  x-amz-id-2: 1Wlw6Edlx3uplC85VIcAwe12xfU8BgcaFHXTlyNBhilk4Xv2sbOJs80FjvAvW9weQkwtKJXcnJg=
  x-amz-request-id: C65B3BF8AC3AA34
status: 409

remembering to keep my XML nicely formatted.

I now have some tests to play with. I can now use these tests to prototype out my code changes and once they are working I should just be able to make the call and and it should just work.

Now where to go?

I know that the code generated from the S3 boto YAML handles at least one error, as there is a test 's3-create-bucket.1.response.test.yml' that checks against a '404' error for the code 'IllegalLocationConstraintException' for a for it so I just look for 'CreateBucket' in the Json data


 "CreateBucket":{
      "name":"CreateBucket",
      "http":{
        "method":"PUT",
        "requestUri":"/{Bucket}"
      },
      "input":{"shape":"CreateBucketRequest"},
      "output":{"shape":"CreateBucketOutput"},
      "errors":[
        {"shape":"BucketAlreadyExists"},
        {"shape":"BucketAlreadyOwnedByYou"}
      ],
…


I see that there are two errors listed under this attribute and I guess I should do the same for my 'RestoreObject' entry.


"RestoreObject":{
      "name":"RestoreObject",
      "http":{
        "method":"POST",
        "requestUri":"/{Bucket}/{Key+}?restore"
      },
      "input":{"shape":"RestoreObjectRequest"},
      "output":{"shape":"RestoreObjectOutput"},
      "errors":[
        {"shape":"ObjectAlreadyInActiveTierError"}
++      {"shape":"ObjectRestoreAlreadyInProgress"}
      ],

and I see I already have one error there 'ObjectAlreadyInActiveTierError' I just add in a new one from my test case and keep the same naming convention 'ObjectRestoreAlreadyInProgress'.

Next I have to add in that new shape into boto like this;


 "ObjectRestoreAlreadyInProgress":{
      "type":"structure",
      "members":{
          "Message":{"shape":"Message"},
          "RequestId":{"shape":"RequestId"}
      },
      "error":{
          "code":"RestoreAlreadyInProgress",
          "httpStatusCode":409
        },
      "documentation":"<p>Object restore is already in progress. (This error does not apply to SELECT type requests.) </p>",
      "exception":true
    },

in the above I am taking a bit of a guess and adding a 'members' section made up of the two items I see in the XML that was returned from before namely 'Message' and ' RequestId'. Now I also have to define in the same file these two types. And I added in;


    "ID":{"type":"string"},
 ++   "Message":{"type":"string"},
 ++   "RequestId":{"type":"string"},
    "IfMatch":{"type":"string"},

and when I compile I get


carton exec builder-bin/gen_classes.pl --classes botocore/botocore/data/s3/2006-03-01/service-2.json
Processing botocore/botocore/data/s3/2006-03-01/service-2.json
Duplicate keys not allowed, at character offset 207745 (before "Message":{"type":"st...") at builder-bin/gen_classes.pl line 78.
Summary of fails:
botocore/botocore/data/s3/2006-03-01/service-2.json Duplicate keys not allowed, at character offset 207745 (before "Message":{"type":"st...") at builder-bin/gen_classes.pl line 78.

Hmm seems I already have "Message":{"type":"string"}, in there so I took that out and then it recompiled correctly;

Now I rerun my test case

...
ok 10210 - Got _status eq 200 from result
ok 10211 - Call S3->RestoreObject from t/10_responses/s3-restore-object.3.response
not ok 10212 - Got request_id eq 195AF4042CD6DF80 from result

# Failed test 'Got request_id eq 195AF4042CD6DF80 from result'
# at t/10_responses.t line 136.
# got: 'AC65B3BF8AC3AA34'
# expected: '195AF4042CD6DF80'
not ok 10213 - Got message eq Object restore is already in progress from result

# Failed test 'Got message eq Object restore is already in progress from result'
# at t/10_responses.t line 136.
# got: 'Conflict'
# expected: 'Object restore is already in progress'
ok 10214 - Got code eq 409 from result

Oh well at least the error code check is working.

Something for tomorrow then.

e7f1db11569b590519cda808402faabe.jpg

Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations