File Coverage

blib/lib/VMware/vCloudDirector2/API.pm
Criterion Covered Total %
statement 223 316 70.5
branch 65 170 38.2
condition 6 14 42.8
subroutine 64 75 85.3
pod n/a
total 358 575 62.2


line stmt bran cond sub pod time code
1             package VMware::vCloudDirector2::API;
2              
3             # ABSTRACT: Module to do stuff!
4              
5 4     4   1359 use strict;
  4         11  
  4         174  
6 4     4   25 use warnings;
  4         9  
  4         136  
7 4     4   60 use v5.10; # needed for state variable
  4         16  
8              
9             our $VERSION = '0.108'; # VERSION
10             our $AUTHORITY = 'cpan:NIGELM'; # AUTHORITY
11              
12 4     4   578 use Moose;
  4         489054  
  4         31  
13 4     4   30200 use Method::Signatures;
  4         70226  
  4         40  
14 4     4   2680 use MooseX::Types::Path::Tiny qw(Path);
  4         561704  
  4         40  
15 4     4   14125 use MooseX::Types::URI qw(Uri);
  4         258293  
  4         30  
16 4     4   12312 use Cpanel::JSON::XS;
  4         12651  
  4         334  
17 4     4   2342 use LWP::UserAgent::Determined;
  4         132282  
  4         166  
18 4     4   2345 use MIME::Base64;
  4         3108  
  4         337  
19 4     4   1898 use Mozilla::CA;
  4         1146  
  4         136  
20 4     4   28 use Path::Tiny;
  4         12  
  4         233  
21 4     4   1970 use Ref::Util qw(is_plain_hashref is_plain_arrayref);
  4         11184  
  4         420  
22 4     4   80 use Scalar::Util qw(looks_like_number);
  4         10  
  4         254  
23 4     4   2345 use Syntax::Keyword::Try 0.04; # Earlier versions throw errors
  4         8447  
  4         23  
24 4     4   2178 use VMware::vCloudDirector2::Error;
  4         16  
  4         202  
25 4     4   2709 use VMware::vCloudDirector2::Object;
  4         19  
  4         228  
26 4     4   2407 use XML::Fast qw(); # just for the versions document
  4         65145  
  4         135  
27 4     4   2081 use Data::Dump qw(pp);
  4         22854  
  4         907  
28              
29             # ------------------------------------------------------------------------
30              
31              
32             has hostname => ( is => 'ro', isa => 'Str', required => 1 );
33             has username => ( is => 'ro', isa => 'Str', required => 1 );
34             has password => ( is => 'ro', isa => 'Str', required => 1 );
35             has orgname => ( is => 'ro', isa => 'Str', required => 1, default => 'System' );
36             has ssl_verify => ( is => 'ro', isa => 'Bool', default => 1 );
37             has debug => ( is => 'rw', isa => 'Int', default => 0, );
38             has timeout => ( is => 'rw', isa => 'Int', default => 120 ); # Defaults to 120 seconds
39             has _debug_trace_directory =>
40             ( is => 'ro', isa => Path, coerce => 1, predicate => '_has_debug_trace_directory' );
41              
42             has default_accept_header => (
43             is => 'ro',
44             isa => 'Str',
45             lazy => 1,
46             builder => '_build_default_accept_header',
47             clearer => '_clear_default_accept_header',
48             );
49              
50             has _base_url => (
51             is => 'ro',
52             isa => Uri,
53             lazy => 1,
54             builder => '_build_base_url',
55             writer => '_set_base_url',
56             clearer => '_clear_base_url',
57             );
58              
59             has ssl_ca_file => (
60             is => 'ro',
61             isa => Path,
62             coerce => 1,
63             lazy => 1,
64             builder => '_build_ssl_ca_file'
65             );
66              
67 4 0   4   4207 method _build_ssl_ca_file () { return path( Mozilla::CA::SSL_ca_file() ); }
  0     0   0  
  0         0  
  0         0  
68 4 50   4   3368 method _build_base_url () { return URI->new( sprintf( 'https://%s/', $self->hostname ) ); }
  1     1   19  
  1         6  
  1         56  
69              
70 4 50   4   3211 method _build_default_accept_header () {
  1     1   4  
  1         4  
71 1         32 return ( 'application/*+json;version=' . $self->api_version );
72             }
73 4 0   4   12694 method _debug (@parameters) { warn join( '', '# ', @parameters, "\n" ) if ( $self->debug ); }
  0     0   0  
  0         0  
  0         0  
74              
75             # ------------------------------------------------------------------------
76              
77 4 50   4   9450 method BUILD ($args) {
  1 50   1   4  
  1         6  
  1         4  
  1         6  
78              
79             # deal with setting debug if needed
80 1         5 my $env_debug = $ENV{VCLOUD_API_DEBUG};
81 1 50       56 if ( defined($env_debug) ) {
82 0 0       0 $self->debug($env_debug) if ( looks_like_number($env_debug) );
83             }
84             }
85              
86             # ------------------------------------------------------------------------
87             has _ua => (
88             is => 'ro',
89             isa => 'LWP::UserAgent',
90             lazy => 1,
91             clearer => '_clear_ua',
92             builder => '_build_ua'
93             );
94              
95             has _ua_module_version => (
96             is => 'ro',
97             isa => 'Str',
98             default => sub { our $VERSION //= '0.00'; sprintf( '%s/%s', __PACKAGE__, $VERSION ) }
99             );
100              
101 4 0   4   3975 method _build_ua () {
  0     0   0  
  0         0  
102 0         0 return LWP::UserAgent::Determined->new(
103             agent => $self->_ua_module_version . ' ',
104             cookie_jar => {},
105             ssl_opts => { verify_hostname => $self->ssl_verify, SSL_ca_file => $self->ssl_ca_file },
106             timeout => $self->timeout,
107             env_proxy => 1,
108             );
109             }
110              
111             # ------------------------------------------------------------------------
112             has _json => (
113             is => 'ro',
114             isa => 'Cpanel::JSON::XS',
115             lazy => 1,
116             builder => '_build_json',
117             );
118              
119 4 50   4   3314 method _build_json () { return Cpanel::JSON::XS->new->utf8->allow_blessed->convert_blessed; }
  1     1   3  
  1         4  
  1         59  
120              
121             # ------------------------------------------------------------------------
122 4 50   4   9106 method _decode_xml_response ($response) {
  1 50   1   3  
  1         5  
  1         3  
  1         4  
123 1         8 my $content = $response->decoded_content;
124 1 50       2269 return if ( length($content) == 0 );
125              
126 1 50       7 VMware::vCloudDirector2::Error->throw(
127             { message => "Not a XML response as expected - $content", response => $response } )
128             unless ( $response->content_type() =~ m|\bxml\b| );
129             try {
130             return unless ( defined($content) and length($content) );
131             return XML::Fast::xml2hash($content);
132             }
133 1         38 catch {
134             VMware::vCloudDirector::Error->throw(
135             { message => "XML decode failed - " . join( ' ', $@ ),
136             response => $response
137             }
138             );
139             }
140             }
141              
142             # ------------------------------------------------------------------------
143 4 50   4   10157 method _decode_json_response ($response) {
  3 50   3   6  
  3         9  
  3         6  
  3         8  
144 3         12 my $content = $response->decoded_content;
145 3 50       389 return if ( length($content) == 0 );
146              
147 3 50       8 VMware::vCloudDirector2::Error->throw(
148             { message => "Not a JSON response as expected - $content",
149             response => $response
150             }
151             ) unless ( $response->content_type() =~ m|\bjson\b| );
152              
153             try {
154             return unless ( defined($content) and length($content) );
155             return $self->_json->decode($content);
156             }
157 3         85 catch {
158             VMware::vCloudDirector2::Error->throw(
159             { message => "JSON decode failed - " . join( ' ', $@ ),
160             response => $response
161             }
162             );
163             }
164             }
165              
166             # ------------------------------------------------------------------------
167 4 0   4   10133 method _encode_json_content ($hash) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
168 0         0 return $self->_json->encode($hash);
169             }
170              
171             # ------------------------------------------------------------------------
172 4 50   4   21660 method _request ($method, $url, $content?, $headers?) {
  4 50   4   10  
  4 50       13  
  4         11  
  4         12  
  4         8  
  4         8  
  4         7  
  4         11  
173 4         152 my $uri = URI->new_abs( $url, $self->_base_url );
174 4 50       1033 $self->_debug("API: _request [$method] $uri") if ( $self->debug );
175              
176 4         22 my $request = HTTP::Request->new( $method => $uri );
177              
178             # build headers
179 4 50 33     325 if ( defined $content && length($content) ) {
180 0         0 $request->content($content);
181 0         0 $request->header( 'Content-Length', length($content) );
182             }
183             else {
184 4         34 $request->header( 'Content-Length', 0 );
185             }
186              
187             # add any supplied headers
188 4         291 my $seen_accept;
189 4 100       16 if ( defined($headers) ) {
190 2         4 foreach my $h_name ( keys %{$headers} ) {
  2         9  
191 2         10 $request->header( $h_name, $headers->{$h_name} );
192 2 100       113 $seen_accept = 1 if ( lc($h_name) eq 'accept' );
193             }
194             }
195              
196             # set accept header
197 4 100       120 $request->header( 'Accept', $self->default_accept_header ) unless ($seen_accept);
198              
199             # set auth header
200 4 100       325 $request->header( 'x-vcloud-authorization', $self->authorization_token )
201             if ( $self->has_authorization_token );
202              
203             # do request
204 4         148 my $response;
205             try { $response = $self->_ua->request($request); }
206 4         12 catch {
207             VMware::vCloudDirector2::Error->throw(
208             { message => "$method request bombed",
209             uri => $uri,
210             request => $request,
211             }
212             );
213             }
214              
215             # if _debug_trace_directory is set - we dump info from each request out into
216             # a pair of files, one with the dumped response object, the other with the content
217 4 50       4717 if ( $self->_has_debug_trace_directory ) {
218 0         0 state $xcount = 0;
219 0 0       0 die "No trace directory - " . $self->_debug_trace_directory
220             unless ( $self->_debug_trace_directory->is_dir );
221 0         0 $self->_debug_trace_directory->child( sprintf( '%06d.txt', ++$xcount ) )
222             ->spew( pp($response) );
223 0 0       0 my $ext = ( $response->content_type =~ /json/ ) ? 'json' : 'xml';
224 0         0 $self->_debug_trace_directory->child( sprintf( '%06d.%s', $xcount, $ext ) )
225             ->spew( $response->decoded_content );
226             }
227              
228             # Throw if this went wrong
229 4 50       15 if ( $response->is_error ) {
230 0         0 my $message = "$method request failed [$uri] - ";
231             try {
232             my $decoded_response = $self->_decode_json_response($response);
233             $message .=
234             ( exists( $decoded_response->{message} ) )
235             ? $decoded_response->{message}
236             : ( 'Unknown after decode: ' . $response->decoded_content );
237             }
238 0         0 catch { $message .= 'Unknown'; }
239 0         0 VMware::vCloudDirector2::Error->throw(
240             { message => $message,
241             uri => $uri,
242             request => $request,
243             response => $response
244             }
245             );
246             }
247              
248 4         44 return $response;
249             }
250              
251             # ------------------------------------------------------------------------
252              
253              
254             has api_version => (
255             is => 'ro',
256             isa => 'Str',
257             lazy => 1,
258             clearer => '_clear_api_version',
259             builder => '_build_api_version'
260             );
261             has _url_login => (
262             is => 'rw',
263             isa => Uri,
264             lazy => 1,
265             clearer => '_clear_url_login',
266             builder => '_build_url_login'
267             );
268             has _url_provider_login => (
269             is => 'rw',
270             isa => Uri,
271             lazy => 1,
272             clearer => '_clear_url_provider_login',
273             builder => '_build_url_provider_login'
274             );
275             has _raw_version => (
276             is => 'rw',
277             isa => 'HashRef',
278             lazy => 1,
279             clearer => '_clear_raw_version',
280             builder => '_build_raw_version'
281             );
282             has _raw_version_full => (
283             is => 'rw',
284             isa => 'HashRef',
285             lazy => 1,
286             clearer => '_clear_raw_version_full',
287             builder => '_build_raw_version_full'
288             );
289              
290 4 50   4   7212 method _build_api_version () { return $self->_raw_version->{Version}; }
  1     1   6  
  1         6  
  1         58  
291 4 0   4   3070 method _build_url_login () { return URI->new( $self->_raw_version->{LoginUrl} ); }
  0     0   0  
  0         0  
  0         0  
292              
293 4 50   4   3084 method _build_url_provider_login () {
  1     1   2  
  1         3  
294 1   33     34 return URI->new( $self->_raw_version->{ProviderLoginUrl} || $self->_raw_version->{LoginUrl} );
295             }
296              
297 4 50   4   3505 method _build_raw_version () {
  1     1   3  
  1         6  
298 1         49 my $hash = $self->_raw_version_full;
299 1         2 my $version = 0;
300 1         2 my $version_block;
301 1         2 for my $verblock ( @{ $hash->{SupportedVersions}{VersionInfo} } ) {
  1         5  
302 13 100 50     32 next if ( ( $verblock->{-deprecated} || '' ) eq 'true' );
303 4 50       16 if ( $verblock->{Version} > $version ) {
304 4         6 $version_block = $verblock;
305 4         9 $version = $verblock->{Version};
306             }
307             }
308              
309 1 50       35 $self->_debug("API: version used: $version") if ( $self->debug );
310 1 50       4 die "No valid version block seen" unless ($version_block);
311              
312 1         34 return $version_block;
313             }
314              
315 4 50   4   3431 method _build_raw_version_full () {
  1     1   4  
  1         5  
316 1         9 my $response = $self->_request( 'GET', '/api/versions', undef, { Accept => 'text/xml' } );
317 1         6 return $self->_decode_xml_response($response);
318             }
319              
320             # ------------------------ ------------------------------------------------
321              
322              
323             has authorization_token => (
324             is => 'ro',
325             isa => 'Str',
326             writer => '_set_authorization_token',
327             clearer => '_clear_authorization_token',
328             predicate => 'has_authorization_token'
329             );
330              
331             has current_session => (
332             is => 'ro',
333             isa => 'Ref',
334             clearer => '_clear_current_session',
335             predicate => 'has_current_session',
336             lazy => 1,
337             builder => '_build_current_session'
338             );
339              
340 4 50   4   3488 method _build_current_session () {
  1     1   2  
  1         4  
341 1         35 my $login_id = join( '@', $self->username, $self->orgname );
342 1         34 my $encoded_auth = 'Basic ' . MIME::Base64::encode( join( ':', $login_id, $self->password ) );
343 1 50       31 $self->_debug("API: attempting login as: $login_id") if ( $self->debug );
344 1 50       30 my $url = ( $self->orgname eq 'System' ) ? $self->_url_provider_login : $self->_url_login;
345 1         3 my $session;
346             my $token;
347 1 50       5 if ( $url =~ m|/cloudapi/| ) {
348 0         0 my $response = $self->_request(
349             'POST', $url, undef,
350             { Authorization => $encoded_auth,
351             Accept => sprintf( "application/json;version=%s", $self->api_version )
352             }
353             );
354 0         0 $session = $self->_decode_json_response($response);
355 0         0 $token = $session->{id};
356 0         0 $token =~ s/.*://;
357 0         0 $token =~ tr/-//d;
358             }
359             else {
360 1         14 my $response = $self->_request( 'POST', $url, undef, { Authorization => $encoded_auth } );
361 1         7 $token = $response->header('x-vcloud-authorization');
362 1         53 ($session) = $self->_build_returned_objects($response);
363             }
364              
365 1         48 $self->_set_authorization_token($token);
366 1 50       36 $self->_debug("API: authentication token: $token") if ( $self->debug );
367              
368             # we also reset the base url to match the login URL
369             ## $self->_set_base_url( $self->_url_login->clone->path('') );
370              
371 1         32 return $session;
372             }
373              
374 4 50   4   4108 method login () { return $self->current_session; }
  1     1   3  
  1         5  
  1         37  
375              
376 4 0   4   3083 method logout () {
  0     0   0  
  0         0  
377 0 0       0 if ( $self->has_current_session ) {
378              
379             # just do this - it might fail, but little you can do now
380             try { $self->DELETE( $self->_url_login ); }
381 0         0 catch { warn "DELETE of session failed: ", @_; }
382             }
383 0         0 $self->_clear_api_data;
384             }
385              
386             # ------------------------------------------------------------------------
387 4 50   4   9418 method _build_returned_objects ($response) {
  2 50   2   5  
  2         8  
  2         3  
  2         6  
388              
389 2 50       8 if ( $response->is_success ) {
390 2 50       92 $self->_debug("API: building objects") if ( $self->debug );
391              
392 2         8 my $hash = $self->_decode_json_response($response);
393 2 50       7 unless ( defined($hash) ) {
394 0 0       0 $self->_debug("API: returned null object") if ( $self->debug );
395 0         0 return;
396             }
397              
398             # See if this is a list of things, in which case the type element will
399             # be thingList and it will have a set of thing in it
400 2         6 my $mime_type = $hash->{type};
401 2 50       14 unless ( defined($mime_type) ) {
402 0         0 $mime_type = $response->header('Content-Type');
403 0         0 $mime_type =~ s/;.*//;
404 0         0 $hash->{type} = $mime_type;
405             }
406 2 50       16 my $type = ( $mime_type =~ m|^application/vnd\..*\.(\w+)\+json$| ) ? $1 : $mime_type;
407 2 100       8 my $thing_type = ( substr( $type, -4, 4 ) eq 'List' ) ? substr( $type, 0, -4 ) : $type;
408              
409 2 100 66     17 if ( ( $type ne $thing_type )
      33        
410             and ( exists( $hash->{$thing_type} ) )
411             and is_plain_arrayref( $hash->{$thing_type} ) ) {
412 1         3 my @thing_objects;
413 1 50       50 $self->_debug("API: building a set of [$thing_type] objects") if ( $self->debug );
414 1         6 foreach my $thing ( $self->_listify( $hash->{$thing_type} ) ) {
415 5         173 my $object = VMware::vCloudDirector2::Object->new(
416             hash => $thing,
417             api => $self,
418             _partial_object => 1
419             );
420 5         16 push @thing_objects, $object;
421             }
422 1         60 return @thing_objects;
423             }
424              
425             # was not a list of things, so just objectify the one thing here
426             else {
427 1 50       144 $self->_debug("API: building a single [$thing_type] object") if ( $self->debug );
428 1         6 return VMware::vCloudDirector2::Object->new(
429             hash => $hash,
430             api => $self,
431             href => $response->request->uri,
432             );
433             }
434             }
435              
436             # there was an error here - so bomb out
437             else {
438 0         0 VMware::vCloudDirector2::Error->throw(
439             { message => 'Error reponse passed to object builder', response => $response } );
440             }
441             }
442              
443             # ------------------------------------------------------------------------
444              
445              
446 4 50   4   11281 method GET ($url) {
  1 50   1   3  
  1         4  
  1         2  
  1         4  
447 1         34 $self->current_session; # ensure/force valid session in place
448 1         5 my $response = $self->_request( 'GET', $url );
449 1         4 return $self->_build_returned_objects($response);
450             }
451              
452 4 50   4   9463 method GET_hash ($url) {
  1 50   1   3  
  1         3  
  1         2  
  1         4  
453 1         33 $self->current_session; # ensure/force valid session in place
454 1         5 my $response = $self->_request( 'GET', $url );
455 1         3 return $self->_decode_json_response($response);
456             }
457              
458 4 0   4   16069 method PUT ($url, $hash, $content_type) {
  0 0   0   0  
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
459 0         0 $self->current_session; # ensure/force valid session in place
460 0 0       0 my $content = is_plain_hashref($hash) ? $self->_encode_json_content($hash) : $hash;
461 0         0 my $response = $self->_request( 'PUT', $url, $content, { 'Content-Type' => $content_type } );
462 0         0 return $self->_build_returned_objects($response);
463             }
464              
465 4 0   4   17085 method POST ($url, $hash, $content_type) {
  0 0   0   0  
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
466 0         0 $self->current_session; # ensure/force valid session in place
467 0 0       0 my $content = is_plain_hashref($hash) ? $self->_encode_json_content($hash) : $hash;
468 0         0 my $response = $self->_request( 'POST', $url, $content, { 'Content-Type' => $content_type } );
469 0         0 return $self->_build_returned_objects($response);
470             }
471              
472 4 0   4   9957 method DELETE ($url) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
473 0         0 $self->current_session; # ensure/force valid session in place
474 0         0 my $response = $self->_request( 'DELETE', $url );
475 0         0 return $self->_build_returned_objects($response);
476             }
477              
478             # ------------------------------------------------------------------------
479              
480              
481             has query_uri => (
482             is => 'ro',
483             isa => Uri,
484             lazy => 1,
485             builder => '_build_query_uri',
486             clearer => '_clear_query_uri',
487             );
488              
489 4 0   4   3625 method _build_query_uri () {
  0     0   0  
  0         0  
490 0         0 my @links = $self->current_session->find_links( rel => 'down', type => 'queryList' );
491 0 0       0 VMware::vCloudDirector2::Error->throw('Cannot find single query URL')
492             unless ( scalar(@links) == 1 );
493 0         0 return $links[0]->href;
494             }
495              
496             # ------------------------------------------------------------------------
497              
498              
499 4 0   4   3364 method _clear_api_data () {
  0     0   0  
  0         0  
500 0         0 $self->_clear_default_accept_header;
501 0         0 $self->_clear_base_url;
502 0         0 $self->_clear_ua;
503 0         0 $self->_clear_api_version;
504 0         0 $self->_clear_url_login;
505 0         0 $self->_clear_url_provider_login;
506 0         0 $self->_clear_raw_version;
507 0         0 $self->_clear_raw_version_full;
508 0         0 $self->_clear_authorization_token;
509 0         0 $self->_clear_current_session;
510 0         0 $self->_clear_query_uri;
511             }
512              
513             # ------------------------------------------------------------------------
514 4 50   4   9385 method _listify ($thing) { !defined $thing ? () : ( ( ref $thing eq 'ARRAY' ) ? @{$thing} : $thing ) }
  1 50   1   3  
  1 50       5  
  1 50       2  
  1         4  
  1         6  
  1         4  
515              
516             # ------------------------------------------------------------------------
517              
518             __PACKAGE__->meta->make_immutable;
519              
520             1;
521              
522             __END__
523              
524             =pod
525              
526             =encoding UTF-8
527              
528             =head1 NAME
529              
530             VMware::vCloudDirector2::API - Module to do stuff!
531              
532             =head1 VERSION
533              
534             version 0.108
535              
536             =head2 Attributes
537              
538             =head3 hostname
539              
540             Hostname of the vCloud server. Must have a vCloud instance listening for https
541             on port 443.
542              
543             =head3 username
544              
545             Username to use to login to vCloud server.
546              
547             =head3 password
548              
549             Password to use to login to vCloud server.
550              
551             =head3 orgname
552              
553             Org name to use to login to vCloud server - this defaults to C<System>.
554              
555             =head3 timeout
556              
557             Command timeout in seconds. Defaults to 120.
558              
559             =head3 default_accept_header
560              
561             The default MIME types to accept. This is automatically set based on the
562             information received back from the API versions.
563              
564             =head3 ssl_verify
565              
566             Whether to do standard SSL certificate verification. Defaults to set.
567              
568             =head3 ssl_ca_file
569              
570             The SSL CA set to trust packaged in a file. This defaults to those set in the
571             L<Mozilla::CA>
572              
573             =head2 debug
574              
575             Set debug level. The higher the debug level, the more chatter is exposed.
576              
577             Defaults to 0 (no output) unless the environment variable C<VCLOUD_API_DEBUG>
578             is set to something that is non-zero. Picked up at create time in C<BUILD()>.
579              
580             =head2 API SHORTHAND METHODS
581              
582             =head3 api_version
583              
584             The C<api_version> holds the version number of the highest discovered non-
585             deprecated API, it is initialised by connecting to the C</api/versions>
586             endpoint, and is called implicitly during the login setup. Once filled the
587             values are cached.
588              
589             =head3 authorization_token
590              
591             The C<authorization_token> holds the vCloud authentication token that has been
592             handed out. It is set by L<login>, and can be tested for by using the
593             predicate C<has_authorization_token>.
594              
595             =head3 current_session
596              
597             The current session object for this login. Attempting to access this forces a
598             login and creation of a current session.
599              
600             =head3 login
601              
602             Returns the L<current_session> which co-incidently forces a login.
603              
604             =head3 logout
605              
606             If there is a current session, DELETEs it, and clears the current session state
607             data.
608              
609             =head3 GET ($url)
610              
611             Forces a session establishment, and does a GET operation on the given URL,
612             returning the objects that were built.
613              
614             =head3 GET_hash ($url)
615              
616             Forces a session establishment, and does a GET operation on the given URL,
617             returning the JSON equivalent hash that was built.
618              
619             =head3 PUT ($url, $hash, $content_type)
620              
621             Forces a session establishment, and does a PUT operation on the given URL,
622             passing the JSON string or encoded hash, returning the objects that were built.
623              
624             =head3 POST ($url, $hash, $content_type)
625              
626             Forces a session establishment, and does a POST operation on the given URL,
627             passing the JSON string or encoded hash, returning the objects that were built.
628              
629             =head3 DELETE ($url)
630              
631             Forces a session establishment, and does a DELETE operation on the given URL,
632             returning the objects that were built.
633              
634             =head3 query_uri
635              
636             Returns the URI for query operations, as taken from the initial session object.
637              
638             =head2 _clear_api_data
639              
640             Clears out all the API state data, including the current login state. This is
641             not intended to be used from outside the module, and will completely trash the
642             current state requiring a new login. The basic information passed at object
643             construction time is not deleted, so a new session could be created.
644              
645             =head1 AUTHOR
646              
647             Nigel Metheringham <nigelm@cpan.org>
648              
649             =head1 COPYRIGHT AND LICENSE
650              
651             This software is copyright (c) 2019 by Nigel Metheringham.
652              
653             This is free software; you can redistribute it and/or modify it under
654             the same terms as the Perl 5 programming language system itself.
655              
656             =cut