Paws XXI (The Adult Version)

We last left out PAWS hero she was just about ready to fix the S3 'PutBucketAnalyticsConfiguration' call. Having first fixed up the botocore json file to properly define the URI for the call.

She now had to find a way to get the 'xmlns' schema attribute add to the root of the XML that is sent to the API.

Turns out I was in very virgin territory there has been no Paws code to take this into account and checking the py code it was not very helpful so I have to put my thinking cap on for this one.

I was thinking I could just make it a new 'trait' like I did for the 'Status' attribute but then I remembered some of my XML from years ago the the 'xmlns' always should be in the root node so It will appear only in one place so not really an attribute trait.

I could just do the same as I did in PAWS 18~19 and add in a 'class' level trait to my template so I tried that change to this template restxml/callargs_class.tt


   [%- IF (traits.size) %], traits => [[% FOREACH trait=traits %]'[% trait %]'[% ',' IF (NOT loop.last) %][% END %]][% END -%]
+  [%- IF (shape.members.$param_name.xmlNamespace) %] [% namspace_uri = shape.members.$param_name.xmlNamespace.uri %][% END %]
   [%- IF (c.required_in_shape(shape,param_name)) %], required => 1[% END %]);
 [% END %]
   use MooseX::ClassAttribute;
-
+  [%- IF namspace_uri %]
+  class_has _namspace_uri => (isa => 'Str', is => 'ro', default => '[% namspace_uri %]');[% END %]
   class_has _api_call => (isa => 'Str', is => 'ro', default => '[% op_name %]');

This I think is the better path for a fix as I do not have to change the boto code. Now if my boto data has the xmlNamespace I just create a variable to hold the value in 'uri' part and then a little later on an if statement to generate the class level attribute for me. It looks like this once compiled;


 has Id => (is => 'ro', isa => 'Str', query_name => 'id', traits => ['ParamInQuery'] , required => 1);

use MooseX::ClassAttribute;
class_has _namspace_uri => (isa => 'Str', is => 'ro', default => 'http://s3.amazonaws.com/doc/2006-03-01/');
class_has _api_call => (isa => 'Str', is => 'ro', default => 'PutBucketAnalyticsConfiguration');



Now I need just a little fix to the 'Paws/Net/RestXmlCaller.pm'


           my $location = $attribute->does('NameInRequest') ? $attribute->request_name : $attribute->name;
-          $xml .= sprintf '<%s>%s</%s>', $location, $self->_to_xml($attribute_value), $location;
+          if ($call->can('_namspace_uri')){
+             $xml .= sprintf '<%s xmlns="%s">%s</%s>', $location, $call->_namspace_uri(),$self->_to_xml($attribute_value), $location;
+                 }
+                 else {
+            $xml .= sprintf '<%s>%s</%s>', $location, $self->_to_xml($attribute_value), $location;
+                 }
         }

all I did in the above is check to see if my '$call' has the '_namspace_uri' attribute by checking with a 'can' and if it does I take the value from that attribute and plug it into the XML as the 'xmlns' tag attribute.

After a quick compile I ran my script and got a '204' response. Which Is really hidden in the back end so like in Paws ?? I would like the see what that response was as I can get a '200' or '204' though I think the doc might be wrong as it says I can only get a '200'

in the json data


 "PutBucketAnalyticsConfiguration":{
      "name":"PutBucketAnalyticsConfiguration",
      "http":{
        "method":"PUT",
        "requestUri":"/{Bucket}?analytics&id={Id}"
      },
      "input":{"shape":"PutBucketAnalyticsConfigurationRequest"},
      "documentation":"<p>Sets an analytics configuration for the bucket (specified by the analytics configuration ID).</p>"
    },

I noticed that there was no 'output' attribute So I created a new one.


"input":{"shape":"PutBucketAnalyticsConfigurationRequest"},
      "output":{"shape":"StatusResponse"},

As I think I will be reusing this more that one I am going to create a generic one like this


    "httpstatus":{"type":"integer"},
    "StatusResonse":{
      "type":"structure",
      "members":{
          "Status":{
          "shape":"httpstatus",
          "documentation":"",
          "location":"statusCode",
          "locationName":"status"
        }
      }
    },
    "Metadata":{

and after a quick compile and a rerun I get this as the final result;


 bless( {
                 'Status' => '204',
                 '_request_id' => '27BAEB9642377092'
               }, 'Paws::S3::StatusResponse' );


Perfect now onto other things.

5bc9058a4188e15e258741c3c1610352.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