File Coverage

blib/lib/Paws.pm
Criterion Covered Total %
statement 89 91 97.8
branch 20 26 76.9
condition 3 3 100.0
subroutine 20 20 100.0
pod 0 6 0.0
total 132 146 90.4


line stmt bran cond sub pod time code
1             package Paws::SDK::Config;
2              
3 22     22   2213691 use Moose;
  22         8514362  
  22         191  
4 22     22   164047 use Moose::Util::TypeConstraints;
  22         59  
  22         229  
5 22     22   66169 use Paws::Net::CallerRole;
  22         129  
  22         832  
6 22     22   11427 use Paws::Credential;
  22         97  
  22         6364  
7              
8             coerce 'Paws::Net::CallerRole',
9             from 'Str',
10             via {
11             my $class = $_;
12             Paws->load_class($class);
13             return $class->new()
14             };
15              
16             coerce 'Paws::Credential',
17             from 'Str',
18             via {
19             my $class = $_;
20             Paws->load_class($class);
21             return $class->new();
22             };
23              
24             has region => (
25             is => 'rw',
26             isa => 'Str|Undef',
27             default => sub { undef }
28             );
29              
30             has caller => (
31             is => 'rw',
32             does => 'Paws::Net::CallerRole',
33             lazy => 1,
34             default => sub {
35             Paws->load_class('Paws::Net::Caller');
36             Paws::Net::Caller->new
37             },
38             coerce => 1
39             );
40             has credentials => (
41             is => 'rw',
42             does => 'Paws::Credential',
43             lazy => 1,
44             default => sub {
45             Paws->load_class('Paws::Credential::ProviderChain');
46             Paws::Credential::ProviderChain->new
47             },
48             coerce => 1
49             );
50             has immutable => (
51             is => 'rw',
52             isa => 'Bool',
53             default => 0,
54             );
55             __PACKAGE__->meta->make_immutable;
56             1;
57              
58             package Paws;
59              
60             our $VERSION = '0.34';
61              
62 22     22   185 use Moose;
  22         57  
  22         128  
63 22     22   180842 use MooseX::ClassAttribute;
  22         2048482  
  22         120  
64 22     22   7123039 use Moose::Util qw//;
  22         60  
  22         436  
65 22     22   150 use Module::Runtime qw//;
  22         44  
  22         592  
66              
67 22     22   14672 use Paws::API::JSONAttribute;
  22         90  
  22         941  
68 22     22   10116 use Paws::API::Base64Attribute;
  22         100  
  22         3516  
69              
70 22     22   10310 use Paws::API;
  22         94  
  22         902  
71 22     22   167 use Moose::Util::TypeConstraints;
  22         47  
  22         232  
72              
73             has _class_prefix => (isa => 'Str', is => 'ro', default => 'Paws::');
74              
75             coerce 'Paws::SDK::Config',
76             from 'HashRef',
77             via {
78             Paws::SDK::Config->new($_);
79             };
80             has config => (isa => 'Paws::SDK::Config', is => 'rw', coerce => 1, default => sub { Paws->default_config });
81              
82             # Holds a fully constructed Paws instance so continuous calls to get_self are all done over the
83             # same (implicit) object. This happens when the user calls Paws->service, as opposed to $instance->service
84             class_has _default_object => (is => 'rw', isa => 'Paws');
85              
86             class_has default_config => (is => 'rw', isa => 'Paws::SDK::Config', default => sub { Paws::SDK::Config->new });
87              
88             sub load_class {
89 13317     13317 0 154386 my (undef, @classes) = @_;
90 13317         47580 foreach my $class (@classes) {
91 13317         72989 Module::Runtime::require_module($class);
92             # immutability is a global setting that will affect all instances
93 13313 50       775481 $class->meta->make_immutable if (Paws->default_config->immutable);
94             }
95             }
96              
97             sub available_services {
98 1     1 0 769 my ($self) = @_;
99 1         5 $self = $self->get_self;
100              
101 1         8 my $skip_list = {
102             API => 1, Credential => 1, Exception => 1, RegionInfo => 1,
103             };
104 1         444 require Module::Find;
105 1         1135 my $class_prefix = $self->_class_prefix;
106 1         37 return grep { not $skip_list->{ $_ } } map { $_ =~ s/^$class_prefix//; $_ } Module::Find::findsubmod Paws;
  105         193  
  105         78763  
  105         181  
107             }
108              
109             sub get_self {
110 1435     1435 0 3344 my $self = shift;
111 1435 100       5414 if (not ref($self)) {
112 110 100       3877 if (not defined Paws->_default_object) {
113 4         124 Paws->_default_object(Paws->new(config => Paws->default_config));
114             }
115 110         2608 return Paws->_default_object;
116             } else {
117 1325         3393 return $self;
118             }
119             }
120              
121             sub class_for_service {
122 768     768 0 2597 my ($self, $service_name) = @_;
123 768         2719 $self = $self->get_self;
124              
125 768         18567 my $class = $self->_class_prefix . $service_name;
126 768         3967 $self->load_class($class);
127 768         3020 return $class;
128             }
129              
130             sub service {
131 666     666 0 24986969 my ($self, $service_name, %constructor_params) = @_;
132 666         3406 $self = $self->get_self;
133              
134 666 100       4258 $constructor_params{ region } = $self->config->region if (not exists $constructor_params{ region });
135 666 100       11123 $constructor_params{ caller } = $self->config->caller if (not exists $constructor_params{ caller });
136 666 100       16869 $constructor_params{ credentials } = $self->config->credentials if (not exists $constructor_params{ credentials });
137              
138 666         2926 my $class = $self->class_for_service($service_name);
139 666         7927 my $instance = $class->new(
140             %constructor_params
141             );
142              
143 665         13172 return $instance;
144             }
145              
146             sub preload_service {
147 102     102 0 4386789 my (undef, $service, @operations) = @_;
148              
149             # load the service class
150 102         766 my $service_class = Paws->class_for_service($service);
151              
152 102 50       637 @operations = ('*') if (@operations == 0);
153              
154 102         525 my %calculated_operations = ();
155 102         359 foreach my $operation (@operations) {
156 102 50       442 if ($operation eq '*') {
    0          
157 102         717 $calculated_operations{ $_ } = 1 for ($service_class->operations);
158             } elsif ($operation =~ m/\*/) {
159 0         0 die "Wildcards not implemented yet";
160             } else {
161 0         0 $calculated_operations{ $operation } = 1;
162             }
163             }
164              
165 102         1125 _preload_operations($service_class, keys %calculated_operations);
166             }
167              
168             sub _preload_operations {
169 102     102   1183 my ($service_class, @operations) = @_;
170              
171 102         357 foreach my $operation (@operations) {
172             # Each operation has two classes associated:
173              
174             # 1st preload the classes that represent the arguments for a call
175 3133         31230 my $op_params_class = "${service_class}::${operation}";
176 3133         11544 _preload_scanclass($op_params_class);
177              
178             # 2nd preload the classes that represent responses from the call
179 3133 50       114947 _preload_scanclass($op_params_class->_returns) if ($op_params_class->_returns);
180             }
181             }
182              
183             sub _preload_scanclass {
184 11132     11132   147702 my ($class) = @_;
185              
186             # If the class is already loaded, we really don't want to be rescanning it
187             # this avoid infinite recursion on DynamoDB, for example
188 11132 100       47264 return if (Moose::Util::find_meta($class));
189              
190 8161         141140 Paws->load_class($class);
191              
192 8161         72099 foreach my $att ($class->meta->get_all_attributes){
193 27877         1473297 my $tconst = $att->type_constraint;
194              
195 27877 100 100     588391 if ($tconst->isa('Moose::Meta::TypeConstraint::Class')) {
    100          
196             # Any attribute that isa class will need to be inspected
197 2778         91599 _preload_scanclass($tconst->class);
198             } elsif ($tconst->isa('Moose::Meta::TypeConstraint::Parameterized') and
199             $tconst->type_parameter->isa('Moose::Meta::TypeConstraint::Class')) {
200             # those attributes can also be found in parametrized
201             # type constraints (ArrayRef[...], Hashref[...])
202 2088         94022 _preload_scanclass($tconst->type_parameter->class);
203             }
204             }
205             }
206              
207             1;
208             ### main pod documentation begin ###
209              
210             =encoding UTF-8
211              
212             =head1 NAME
213              
214             Paws - A Perl SDK for AWS (Amazon Web Services) APIs
215              
216             =head1 SYNOPSIS
217              
218             use Paws;
219             my $obj = Paws->service('...');
220             my $res = $obj->MethodCall(Arg1 => $val1, Arg2 => $val2);
221             print $res->AttributeFromResult;
222              
223             =head1 DESCRIPTION
224              
225             Paws is an attempt to develop an always up-to-date SDK that covers all possible AWS services.
226              
227             =head1 STATUS
228              
229             Please consider the SDK is beta quality. The intention of publishing to CPAN is having the community
230             find the SDK, try it, give feedback, etc. Some services are still not working, and some heavy
231             refactoring will still be done to the internals. The external interface to SDK users will try to be
232             kept stable, and changes to it should be notified via ChangeLog
233              
234             =head1 SUPPORTED SERVICES
235              
236              
237             L<Paws::ACM>
238              
239             L<Paws::ApiGateway>
240              
241             L<Paws::ApplicationAutoScaling>
242              
243             L<Paws::AppStream>
244              
245             L<Paws::Athena>
246              
247             L<Paws::AutoScaling>
248              
249             L<Paws::Batch>
250              
251             L<Paws::Budgets>
252              
253             L<Paws::CloudDirectory>
254              
255             L<Paws::CloudFormation>
256              
257             L<Paws::CloudFront>
258              
259             L<Paws::CloudHSM>
260              
261             L<Paws::CloudSearch>
262              
263             L<Paws::CloudSearchDomain>
264              
265             L<Paws::CloudTrail>
266              
267             L<Paws::CloudWatch>
268              
269             L<Paws::CloudWatch>
270              
271             L<Paws::CloudWatchEvents>
272              
273             L<Paws::CloudWatchLogs>
274              
275             L<Paws::CodeBuild>
276              
277             L<Paws::CodeCommit>
278              
279             L<Paws::CodeDeploy>
280              
281             L<Paws::CodePipeline>
282              
283             L<Paws::CodeStar>
284              
285             L<Paws::CognitoIdentity>
286              
287             L<Paws::CognitoIdp>
288              
289             L<Paws::CognitoSync>
290              
291             L<Paws::Config>
292              
293             L<Paws::CUR>
294              
295             L<Paws::DataPipeline>
296              
297             L<Paws::DAX>
298              
299             L<Paws::DeviceFarm>
300              
301             L<Paws::DirectConnect>
302              
303             L<Paws::Discovery>
304              
305             L<Paws::DMS>
306              
307             L<Paws::DS>
308              
309             L<Paws::DynamoDB>
310              
311             L<Paws::DynamoDBStreams>
312              
313             L<Paws::EC2>
314              
315             L<Paws::ECR>
316              
317             L<Paws::ECS>
318              
319             L<Paws::EFS>
320              
321             L<Paws::ElastiCache>
322              
323             L<Paws::ElasticBeanstalk>
324              
325             L<Paws::ElasticTranscoder>
326              
327             L<Paws::ELB>
328              
329             L<Paws::ELB>
330              
331             L<Paws::ELBv2>
332              
333             L<Paws::EMR>
334              
335             L<Paws::EMR>
336              
337             L<Paws::ES>
338              
339             L<Paws::Firehose>
340              
341             L<Paws::GameLift>
342              
343             L<Paws::Glacier>
344              
345             L<Paws::Greengrass>
346              
347             L<Paws::Health>
348              
349             L<Paws::IAM>
350              
351             L<Paws::ImportExport>
352              
353             L<Paws::Inspector>
354              
355             L<Paws::IoT>
356              
357             L<Paws::IoTData>
358              
359             L<Paws::Kinesis>
360              
361             L<Paws::KinesisAnalytics>
362              
363             L<Paws::KMS>
364              
365             L<Paws::Lambda>
366              
367             L<Paws::LexModels>
368              
369             L<Paws::LexRuntime>
370              
371             L<Paws::Lightsail>
372              
373             L<Paws::MachineLearning>
374              
375             L<Paws::MarketplaceCommerceAnalytics>
376              
377             L<Paws::MarketplaceEntitlement>
378              
379             L<Paws::MarketplaceMetering>
380              
381             L<Paws::MTurk>
382              
383             L<Paws::OpsWorks>
384              
385             L<Paws::OpsWorksCM>
386              
387             L<Paws::Organizations>
388              
389             L<Paws::Pinpoint>
390              
391             L<Paws::Polly>
392              
393             L<Paws::RDS>
394              
395             L<Paws::RedShift>
396              
397             L<Paws::Rekognition>
398              
399             L<Paws::ResourceTagging>
400              
401             L<Paws::Route53>
402              
403             L<Paws::Route53Domains>
404              
405             L<Paws::S3>
406              
407             L<Paws::SDB>
408              
409             L<Paws::ServiceCatalog>
410              
411             L<Paws::SES>
412              
413             L<Paws::SES>
414              
415             L<Paws::Shield>
416              
417             L<Paws::Signin>
418              
419             L<Paws::SimpleDB>
420              
421             L<Paws::SimpleWorkflow>
422              
423             L<Paws::SMS>
424              
425             L<Paws::Snowball>
426              
427             L<Paws::SNS>
428              
429             L<Paws::SQS>
430              
431             L<Paws::SSM>
432              
433             L<Paws::StepFunctions>
434              
435             L<Paws::StorageGateway>
436              
437             L<Paws::STS>
438              
439             L<Paws::Support>
440              
441             L<Paws::WAF>
442              
443             L<Paws::WAFRegional>
444              
445             L<Paws::WorkDocs>
446              
447             L<Paws::WorkSpaces>
448              
449             L<Paws::XRay>
450              
451              
452             =head1 SERVICES CLASSES
453              
454             Each service in AWS (EC2, CloudFormation, SQS, SNS, etc) has a service class. The service class represents the properties that a web service has (how to call it, what methods it has, how to authenticate, etc). When a service class is instantiated with the right properties (region, if needed, credentials, caller, etc), it will be able to make calls to the service.
455              
456             Service classes are obtained through
457              
458             my $service_class = Paws->class_for_service('Service');
459             my $service_object = $service_class->new(region => '...', caller => ...)
460              
461             Although they are seldom needed. 99% of the time you want service objects directly obtained with the ->service method (read next section) since you have to write less code.
462              
463             =head1 SERVICE OBJECTS
464              
465             Each Service Object represents the ability to call methods on a service endpoint. Those endpoints are
466             either global, or bound to a region depending on the service. Also, each object can be customized
467             with a credential provider, that tells the object where to obtain credentials for the call (you can
468             get them from the environment, from the filesystem, from the AWS Instance Profile, STS, etc.
469              
470             To obtain a service object, call the C<< ->service >> method
471              
472             use Paws;
473             my $service = Paws->service('Service');
474              
475             You can pass extra parameters if the service is bound to a region:
476              
477             my $service = Paws->service('Service', region => 'us-east-1');
478              
479             These parameters are basically passed to the service class constructor
480              
481             =head1 AUTHENTICATION
482              
483             Service classes by default try to authenticate with a chained authenticator. The chained authenticator tries to first find credentials in your environment variables B<AWS_ACCESS_KEY> and B<AWS_SECRET_KEY> (note that B<AWS_ACCESS_KEY_ID> and B<AWS_SECRET_ACCESS_KEY> are also scanned for compatibility with the official SDKs). Second, it will look for credentials in the B<default> profile of the B<~/.aws/credentials> or the file in B<AWS_CONFIG_FILE> env variable (an ini-formatted file). Last, if no environment variables are found, then a call to retrieve Role credentials is done. If your instance is running on an AWS instance, and has a Role assigned, the SDK will automatically retrieve credentials to call any services that the instances Role permits.
484              
485             Please never burn credentials into your code. That's why the methods for passing an explicit access key and secret key are not documented.
486              
487             So, instantiating a service with
488              
489             my $ec2 = Paws->service('EC2', region => 'eu-west-1');
490              
491             we get an service object that will try to authenticate with environment, credential file, or an instance role.
492              
493             When instantiating a service object, you can also pass a custom credential provider:
494              
495             use Paws::Credential::STS;
496              
497             my $cred_provider = Paws::Credential::STS->new(
498             Name => 'MyName',
499             DurationSeconds => 900,
500             Policy => '{"Version":"2012-10-17","Statement":[{"Effect": "Allow","Action":["ec2:DescribeInstances"],"Resource":"*"}]}'
501             );
502             my $ec2 = Paws->service('EC2', credentials => $cred_provider, region => 'eu-west-1');
503              
504             In this example we instance a service object that uses the STS service to create temporary credentials that only let the service object call DescribeInstances.
505              
506             Paws bundles some pre-baked credential providers:
507              
508             L<Paws::Credential::ProviderChain> - Gets credentials from a list of providers, returning the first provider to return credentials
509              
510             L<Paws::Credential::Environment> - Gets credentials from environment variables
511              
512             L<Paws::Credential::File> - Gets credentials from AWS SDK config files
513              
514             L<Paws::Credential::InstanceProfile> - Gets credentials from the InstanceProfile (Role) of the running instance
515              
516             L<Paws::Credential::STS> - Gets temporary credentials from the Secure Token Service
517              
518             L<Paws::Credential::AssumeRole> - Gets temporary credentials with AssumeRole
519              
520             L<Paws::Credential::AssumeRoleWithSAML> - Gets temporary credentials with AssumeRoleWithSAML
521              
522             L<Paws::Credential::Explicit> - Gets credentials specified in the code
523              
524             =head1 Using Service objects (Calling APIs)
525              
526             Each API call is represented as a method call with the same name as the API call. The arguments to the call are passed as lists (named parameters) to the call. So, to call DescribeInstances on the EC2 service:
527              
528             my $result = $ec2->DescribeInstances;
529              
530             The DescribeInstances call has no required parameters, but if needed, we can pass them in (you can look them up in L<Paws::EC2> and see detail in L<Paws::EC2::DescribeInstances>
531              
532             my $result = $ec2->DescribeInstances(MaxResults => 5);
533              
534             If the parameter is an Array:
535              
536             my $result = $ec2->DescribeInstances(InstanceIds => [ 'i-....' ]);
537              
538             If the parameter to be passed in is a complex value (an object)
539              
540             my $result = $ec2->DescribeInstances(Filters => [ { Name => '', Value => '' } ])
541              
542             =head1 RETURN VALUES
543              
544             The AWS APIs return nested datastructures in various formats. The SDK converts these datastructures into objects that can then be used as wanted.
545              
546             my $private_dns = $result->Reservations->[0]->Instances->[0]->PrivateDnsName;
547              
548             =head1 CONFIGURATION
549              
550             Paws instances have a configuration. The configuration is basically a specification of values that will be passed to the service method each time
551             it's called
552              
553             # the credentials and the caller keys accept an instance or the name of a class as a
554             # string (the class will be loaded and the constructor of that class will be automatically called
555             my $paws1 = Paws->new(config => { credentials => MyCredProvider->new, region => 'eu-west-1' });
556             my $paws2 = Paws->new(config => { caller => 'MyCustomCaller' });
557            
558             # EC2 service with MyCredProvider in eu-west-1
559             my $ec2 = $paws1->service('EC2');
560              
561             # DynamoDB service with MyCustomCaller in us-east-1. region is needed because it's not in the config
562             my $ddb = $paws2->service('DynamoDB', region => 'us-east-1');
563              
564             # DynamoDB in eu-west-1 with MyCredProvider
565             my $other_ddb = $paws1->service('DynamoDB');
566              
567             The attributes that can be configured are:
568              
569             =head3 credentials
570              
571             Accepts a string which value is the name of a class, or an already instantiated object. If a string is passed, the class will be loaded, and the
572             constructor called (without parameters). Also, the resulting instance or the already instantiated object has to have the L<Paws::Credential> role.
573              
574             =head3 caller
575              
576             Accepts a string which value is the name of a class, or an already instantiated object. If a string is passed, the class will be loaded, and the
577             constructor called (without parameters). Also, the resulting instance or the already instantiated object has to have the L<Paws::Net::CallerRole> role.
578              
579             =head3 region
580              
581             A string representing the region that service objects will be instantiated with. Most services need a region specified, meaning that you will have to specify the desired region every time you call the B<service> method.
582              
583             my $cfn = Paws->service('CloudFormation', region => 'eu-west-1');
584              
585             Some services (like IAM) are global, so they don't need their region specified:
586              
587             my $iam = Paws->service('IAM');
588              
589             A special service is STS, which by default has a global endpoint, but you can also specify regional endpoints
590              
591             my $global_sts = Paws->service('STS');
592             my $regional_sts = Paws->service('STS', region => 'eu-west-1');
593              
594             =head3 endpoint
595              
596             Paws needs to send HTTP requests to different URLS (endpoints) depending on the service and the region. URLs are normally automatically derived by specifying the region, but for special cases, like pointing to "fake-sqs" or "fake-s3" services, you can:
597              
598             Paws->service('SQS', endpoint => 'http://localhost:3000', region => 'eu-west-1');
599              
600             Some services, like the MachineLearning predictor API want you to specify a custom endpoint:
601              
602             my $model = $ml->GetMLModel(MLModelId => $model_id);
603             my $predictor = Paws->service('ML', endpoint => $model->EndpointInfo->EndpointUrl, region => 'eu-west-1');
604             $predictor->...
605              
606             =head1 Pluggability
607              
608             =head2 Credential Provider Pluggability
609              
610             Credential classes need to have the Role L<Paws::Credential> applied. This obliges them to implement access_key, secret_key and session_token methods.
611             The obtention of this data can be customized to be retrieved whereever the developer considers useful (files, environment, other services, etc). Take
612             a look at the Paws::Credential::XXXX namespace to find already implemented credential providers.
613              
614             The credential objects' access_key, secret_key and session_token methods will be called each time an API call has to be signed.
615              
616             =head2 Caller Pluggability
617              
618             Caller classes need to have the Role L<Paws::Net::CallerRole> applied. This obliges them to implement the do_call method. Tests use this interface to
619             mock calls and responses to the APIs (without using the network).
620              
621             The caller instance is responsable for doing the network Input/Output with some type of HTTP request library, and returning the Result from the API.
622              
623             These callers are included and supported in Paws:
624              
625             L<Paws::Net::Caller>: Uses HTTP::Tiny. It's the default caller for Paws
626              
627             L<Paws::Net::MojoAsyncCaller>: Experimental asyncronous IO caller. Paws method calls return futures instead of results
628              
629             L<Paws::Net::LWPCaller>: Uses LWP. LWP supports HTTPS proxies, so Paws can call AWS from behind an HTTPS proxy.
630              
631             L<Paws::Net::FurlCaller>: Uses Furl: a lightning fast HTTP client
632              
633             =head1 Optimization
634              
635             =head2 Preloading services and operations
636              
637             Paws->preload_service($service)
638             Paws->preload_service($service, @methods)
639              
640             Paws manages a lot of objects that are loaded dynamically as needed. This causes high memory consumption if you do operations with Paws in a forked
641             environment because each child loads a separate copy of all the classes it needs to do the calls. Paws provides the preload_service operation. Call
642             it with the name of the service before forking off so your server can benefit from copy on write memory sharing. The parent class will load all the
643             classes needed so that child processes don't need to load them.
644              
645             Some classes have lot's of calls, so preloading them can be quite expensive. If you call preload_service with a list of the methods you will call,
646             it will only load classes needed for those calls. This is specially useful for L<Paws::EC2>, for example.
647              
648             Preloading doesn't change the usage of Paws. That means that all services and methods still work without any change, just that if they're not preloaded
649             they'll be loaded at runtime.
650              
651             =head2 Immutabilizing classes
652              
653             Paws objects are programmed with L<Moose> (the Modern Perl Object Framework). Moose objects can be immutibilized so that method calls perform better,
654             at the cost of startup time. If you deem your usage of Paws to be long-lived, you can call
655              
656             Paws->default_config->immutable(1);
657              
658             as early as possible in the code. Very important that the immutable flag be activated before calling preload_service.
659              
660             =head1 AUTHOR
661              
662             Jose Luis Martinez
663             CPAN ID: JLMARTIN
664             CAPSiDE
665             jlmartinez@capside.com
666              
667             =head1 SEE ALSO
668              
669             L<http://aws.amazon.com/documentation/>
670              
671             L<https://github.com/pplu/aws-sdk-perl>
672              
673             =head1 BUGS and SOURCE
674              
675             The source code is located here: https://github.com/pplu/aws-sdk-perl
676              
677             Please report bugs to: https://github.com/pplu/aws-sdk-perl/issues
678              
679             =head1 COPYRIGHT and LICENSE
680              
681             Copyright (c) 2015 by Jose Luis Martinez Torres
682              
683             This code is distributed under the Apache 2 License. The full text of the license can be found in the LICENSE file included with this module.
684              
685             =head1 CONTRIBUITIONS
686              
687              
688             CAPSiDE (http://www.capside.com) for letting Paws be contributed in an open source model
689             and giving me time to build and maintain it regularly
690              
691             Luis Alberto Gimenez (@agimenez) for
692             - The git-fu cleaning up the "pull other sdks" code
693             - Credential Providers code
694             - Fixes for users that have no HOME env variable
695             - FileCaller to fully mock responses
696              
697             Srinvas (@kidambisrinivas) for testing, bug reporting and fixing
698              
699             juair10 for corrections and testing
700              
701             CHORNY for CPAN and cpanfile packaging corrections
702              
703             Iñigo Tejedor for service endpoint resolution based on rules
704              
705             codehead for helping fix SQS Queue Maps
706              
707             mbartold for helping fix SQS MessageBatch functionality
708              
709             coreymayer for reporting bug in RestXmlCaller
710              
711             arc (Aaron Crane) for documentation patches
712              
713             dtikhonov for LWP Caller and bug reporting/fixing
714              
715             vivus-ignis for DynamoDB bug reporting and test scripts for DynamoDB
716              
717             karenetheridge for bug reporting, pull requests and help
718              
719             ioanrogers for fixing unicode issues in tests
720              
721             ilmari for fixing issues with timestamps in Date and X-Amz-Date headers,
722             test fixes and 5.10 support fixes, documentation issue fixes for S3,
723             CloudFront and Route53, help with number stringification
724              
725             stevecaldwell77 for contributing support for temporary credentials in S3
726              
727             Ryan Olson (BeerBikesBBQ) for contributing documentation fixes
728              
729             Roger Pettett for testing and contributing fixes for tests on MacOSX
730              
731             Henri Yandell for help with licensing issues
732              
733             Oriol Soriano (@ureesoriano) for contribution to API builders
734              
735             H. Daniel Cesario (@maneta) for devel setup instructions on RH and MacOSX
736              
737             Glen van Ginkel for contributions to get S3 working
738              
739             Javier Arellano for discovering Tagging bug
740              
741             Ioan Rogers for contributing AssumeRoleWithSAML with ADFS auth example
742              
743             Miquel Soriano for reporting a bug with DescribeAutoScalingGroups
744              
745             Albert Bendicho (wiof) for contributing better retry logic
746              
747             Brian Hartsock for better handling of XMLResponse exceptions
748              
749             rpcme for reporting various bugs in the SDK
750              
751             glenveegee for lots of work sorting out the S3 implementation
752              
753             Grinzz for many bugs, suggestions and fixes
754              
755             Dakkar for solving issues with parameter passing
756              
757             Arthur Axel fREW Schmidt for speeding up credential refreshing
758              
759             PopeFelix for solving issues around S3 and MojoAsyncCaller
760              
761             meis for contributing Paws::Credential::Explicit
762              
763             sven-schubert for contributing fixes to RestXML services
764              
765             SeptamusNonovant for fixing paginators in non-callback mode
766              
767             gadgetjunkie for contributing the ECS credential provider
768              
769              
770             =cut