File Coverage

blib/lib/AWS/CLIWrapper.pm
Criterion Covered Total %
statement 41 491 8.3
branch 6 84 7.1
condition 3 48 6.2
subroutine 11 359 3.0
pod 344 348 98.8
total 405 1330 30.4


line stmt bran cond sub pod time code
1             package AWS::CLIWrapper;
2              
3 6     6   274908 use 5.008001;
  6         50  
4 6     6   27 use strict;
  6         10  
  6         98  
5 6     6   32 use warnings;
  6         9  
  6         215  
6              
7             our $VERSION = '1.25';
8              
9 6     6   2120 use version;
  6         9231  
  6         26  
10 6     6   3455 use JSON 2;
  6         57333  
  6         28  
11 6     6   4035 use IPC::Cmd;
  6         286478  
  6         270  
12 6     6   2411 use String::ShellQuote;
  6         4011  
  6         294  
13 6     6   38 use Carp;
  6         13  
  6         44822  
14              
15             our $Error = { Message => '', Code => '' };
16              
17             our $true = do { bless \(my $dummy = 1), "AWS::CLIWrapper::Boolean" };
18             our $false = do { bless \(my $dummy = 0), "AWS::CLIWrapper::Boolean" };
19              
20             my $AWSCLI_VERSION = undef;
21              
22             sub new {
23 7     7 1 4631 my($class, %param) = @_;
24              
25 7         18 my @opt = ();
26 7         15 for my $k (qw(region profile endpoint_url)) {
27 21 50       50 if (my $v = delete $param{$k}) {
28 0         0 push @opt, param2opt($k, $v);
29             }
30             }
31              
32             my $self = bless {
33             opt => \@opt,
34             json => JSON->new,
35             awscli_path => $param{awscli_path} || 'aws',
36             croak_on_error => !!$param{croak_on_error},
37 7 100 100     239 timeout => (defined $ENV{AWS_CLIWRAPPER_TIMEOUT}) ? $ENV{AWS_CLIWRAPPER_TIMEOUT} : 30,
38             }, $class;
39              
40 7         28 return $self;
41             }
42              
43             sub awscli_path {
44 4     4 0 13 my ($self) = @_;
45 4         19 return $self->{awscli_path};
46             }
47              
48             sub awscli_version {
49 4     4 0 20 my ($self) = @_;
50 4 100       16 unless (defined $AWSCLI_VERSION) {
51 2         4 $AWSCLI_VERSION = do {
52 2         6 my $awscli_path = $self->awscli_path;
53 2   50     5093 my $vs = qx($awscli_path --version 2>&1) || '';
54 2         27 my $v;
55 2 50       47 if ($vs =~ m{/([0-9.]+)\s}) {
56 0         0 $v = $1;
57             } else {
58 2         8 $v = 0;
59             }
60 2         131 version->parse($v);
61             };
62             }
63 4         109 return $AWSCLI_VERSION;
64             }
65              
66             sub param2opt {
67 0     0 0   my($k, $v) = @_;
68              
69 0           my @v;
70              
71 0           $k =~ s/_/-/g;
72 0           $k = '--'.$k;
73              
74 0           my $type = ref $v;
75 0 0         if (! $type) {
    0          
    0          
    0          
76 0 0         if ($k eq '--output-file') {
77             # aws s3api get-object takes a single arg for output file path
78 0           return $v;
79             } else {
80 0           push @v, $v;
81             }
82             } elsif ($type eq 'ARRAY') {
83 0 0         push @v, map { ref($_) ? encode_json(_compat_kv($_)) : $_ } @$v;
  0            
84             } elsif ($type eq 'HASH') {
85 0           push @v, encode_json(_compat_kv($v));
86             } elsif ($type eq 'AWS::CLIWrapper::Boolean') {
87 0 0         if ($$v == 1) {
88 0           return ($k);
89             } else {
90 0           return ();
91             }
92             } else {
93 0           push @v, $v;
94             }
95              
96 0           return ($k, @v);
97             }
98              
99             # >= 0.14.0 : Key, Values, Value, Name
100             # < 0.14.0 : key, values, value, name
101             sub _compat_kv_uc {
102 0     0     my $v = shift;
103 0           my $type = ref $v;
104              
105 0 0 0       if ($type && $type eq 'HASH') {
106 0           for my $hk (keys %$v) {
107 0 0         if ($hk =~ /^(?:key|name|values|value)$/) {
108 0           $v->{ucfirst($hk)} = delete $v->{$hk};
109             }
110             }
111             }
112              
113 0           return $v;
114             }
115             # sub _compat_kv_lc {
116             # my $v = shift;
117             # my $type = ref $v;
118              
119             # if ($type && $type eq 'HASH') {
120             # for my $hk (keys %$v) {
121             # if ($hk =~ /^(?:Key|Name|Values|Values)$/) {
122             # $v->{lc($hk)} = delete $v->{$hk};
123             # }
124             # }
125             # }
126              
127             # return $v;
128             # }
129             # Drop support < 0.14.0 for preventing execute aws command in loading this module
130             *_compat_kv = *_compat_kv_uc;
131              
132 0     0 0   sub json { $_[0]->{json} }
133              
134             sub _execute {
135 0     0     my $self = shift;
136 0           my $service = shift;
137 0           my $operation = shift;
138 0           my @cmd = ($self->awscli_path, @{$self->{opt}}, $service, $operation);
  0            
139 0 0 0       if ($service eq 'ec2' && $operation eq 'wait') {
140 0           push(@cmd, shift @_);
141             }
142 0 0         if (ref($_[0]) eq 'ARRAY') {
143             # for s3 sync FROM TO
144 0           push @cmd, @{ shift @_ };
  0            
145             }
146 0           my($param, %opt) = @_;
147              
148 0 0 0       if ($service eq 'ec2' && $operation eq 'run-instances') {
    0 0        
    0 0        
149             # compat: ec2 run-instances
150             # >= 0.14.0 : --count N or --count MIN:MAX
151             # < 0.14.0 : --min-count N and --max-count N
152 0 0         if ($self->awscli_version >= 0.14.0) {
153 0           my($min,$max) = (1,1);
154 0           for my $hk (keys %$param) {
155 0 0         if ($hk eq 'min_count') {
    0          
156 0           $min = delete $param->{min_count};
157             } elsif ($hk eq 'max_count') {
158 0           $max = delete $param->{max_count};
159             }
160             }
161             $param->{count} = "${min}:${max}" unless $param->{count}
162 0 0         } else {
163 0           my($min,$max);
164 0           for my $hk (keys %$param) {
165 0 0         if ($hk eq 'count') {
166 0           ($min,$max) = split /:/, delete($param->{count});
167 0   0       $max ||= $min;
168 0           last;
169             }
170             }
171 0 0         $param->{min_count} = $min unless $param->{min_count};
172 0 0         $param->{max_count} = $max unless $param->{max_count};
173             }
174             } elsif ($service eq 's3' && $self->awscli_version >= 0.15.0) {
175 0 0         if ($operation !~ /^(?:cp|ls|mb|mv|rb|rm|sync|website)$/) {
176 0           return $self->s3api($operation, @_);
177             }
178             } elsif ($service eq 's3api' && $self->awscli_version < 0.15.0) {
179 0           return $self->s3($operation, @_);
180             }
181              
182 0           while (my($k, $v) = each %$param) {
183 0           my @o = param2opt($k, $v);
184 0 0 0       if ($service eq 's3' && $k =~ /^(?:include|exclude)$/) {
185 0           my $optk = shift @o;
186 0           @o = map { $optk => $_ } @o;
  0            
187             }
188 0           push @cmd, @o;
189             }
190 0           @cmd = map { shell_quote($_) } @cmd;
  0            
191 0 0         warn "cmd: ".join(' ', @cmd) if $ENV{AWSCLI_DEBUG};
192              
193 0           my $ret;
194 0 0 0       if (exists $opt{'nofork'} && $opt{'nofork'}) {
195             # better for perl debugger
196             my($ok, $err, $buf, $stdout_buf, $stderr_buf) = IPC::Cmd::run(
197             command => join(' ', @cmd),
198             timeout => $opt{timeout} || $self->{timeout},
199 0   0       );
200 0           $ret->{stdout} = join "", @$stdout_buf;
201 0 0         $ret->{err_msg} = (defined $err ? "$err\n" : "") . join "", @$stderr_buf;
202 0 0         if ($ok) {
203 0           $ret->{exit_code} = 0;
204 0           $ret->{timeout} = 0;
205             } else {
206 0           $ret->{exit_code} = 2;
207 0 0 0       $ret->{timeout} = 1 if defined $err && $err =~ /^IPC::Cmd::TimeOut:/;
208             }
209 0           print "";
210             } else {
211             $ret = IPC::Cmd::run_forked(join(' ', @cmd), {
212             timeout => $opt{timeout} || $self->{timeout},
213 0   0       });
214             }
215              
216 0 0 0       if ($ret->{exit_code} == 0 && $ret->{timeout} == 0) {
217 0           my $json = $ret->{stdout};
218             warn sprintf("%s.%s[%s]: %s\n",
219             $service, $operation, 'OK', $json,
220 0 0         ) if $ENV{AWSCLI_DEBUG};
221 0           local $@;
222 0           my($ret) = eval {
223             # aws s3 returns null HTTP body, so failed to parse as JSON
224              
225             # Temporary disable __DIE__ handler to prevent the
226             # exception from decode() from catching by outer
227             # __DIE__ handler.
228 0     0     local $SIG{__DIE__} = sub {};
229              
230 0           $self->json->decode($json);
231             };
232 0 0         if ($@) {
233 0 0         if ($ENV{AWSCLI_DEBUG}) {
234 0           warn $@;
235 0           warn qq|stdout: "$ret->{stdout}"|;
236 0           warn qq|err_msg: "$ret->{err_msg}"|;
237             }
238 0   0       return $json || 'success';
239             }
240 0           return $ret;
241             } else {
242 0           my $stdout_str = $ret->{stdout};
243 0 0 0       if ($stdout_str && $stdout_str =~ /^{/) {
244 0           my $json = $stdout_str;
245             warn sprintf("%s.%s[%s]: %s\n",
246             $service, $operation, 'NG', $json,
247 0 0         ) if $ENV{AWSCLI_DEBUG};
248 0           my($ret) = $self->json->decode_prefix($json);
249 0 0 0       if (exists $ret->{Errors} && ref($ret->{Errors}) eq 'ARRAY') {
    0          
250 0           $Error = $ret->{Errors}[0];
251             } elsif (exists $ret->{Response}{Errors}{Error}) {
252             # old structure (maybe botocore < 0.7.0)
253 0           $Error = $ret->{Response}{Errors}{Error};
254             } else {
255 0           $Error = { Message => 'Unknown', Code => 'Unknown' };
256             }
257             } else {
258 0           my $msg = $ret->{err_msg};
259             warn sprintf("%s.%s[%s]: %s\n",
260             $service, $operation, 'NG', $msg,
261 0 0         ) if $ENV{AWSCLI_DEBUG};
262 0           $Error = { Message => $msg, Code => 'Unknown' };
263             }
264              
265 0 0         croak $Error->{Message} if $self->{croak_on_error};
266              
267 0           return;
268             }
269             }
270              
271             # aws help | col -b | perl -ne 'if (/^AVAILABLE/.../^[A-Z]/) { s/^\s+o\s+// or next; chomp; next if $_ eq 'help'; my $sn = $_; $sn =~ s/-/_/g; printf "sub %-18s { shift->_execute('"'"'%s'"'"', \@_) }\n", $sn, $_ }'
272             # aws help | col -b | perl -ne 'if (/^AVAILABLE/.../^[A-Z]/) { s/^\s+o\s+// or next; chomp; next if $_ eq 'help'; my $sn = $_; $sn =~ s/-/_/g; printf "=item B<%s>(\$operation:Str, \$param:HashRef, %%opt:Hash)\n\n", $sn}'
273             # =item B($operation:Str, $path:ArrayRef, $param:HashRef, %opt:Hash)
274 0     0 1   sub accessanalyzer { shift->_execute('accessanalyzer', @_) }
275 0     0 1   sub account { shift->_execute('account', @_) }
276 0     0 1   sub acm { shift->_execute('acm', @_) }
277 0     0 1   sub acm_pca { shift->_execute('acm-pca', @_) }
278 0     0 1   sub alexaforbusiness { shift->_execute('alexaforbusiness', @_) }
279 0     0 1   sub amp { shift->_execute('amp', @_) }
280 0     0 1   sub amplify { shift->_execute('amplify', @_) }
281 0     0 1   sub amplifybackend { shift->_execute('amplifybackend', @_) }
282 0     0 1   sub amplifyuibuilder { shift->_execute('amplifyuibuilder', @_) }
283 0     0 1   sub apigateway { shift->_execute('apigateway', @_) }
284 0     0 1   sub apigatewaymanagementapi { shift->_execute('apigatewaymanagementapi', @_) }
285 0     0 1   sub apigatewayv2 { shift->_execute('apigatewayv2', @_) }
286 0     0 1   sub appconfig { shift->_execute('appconfig', @_) }
287 0     0 1   sub appconfigdata { shift->_execute('appconfigdata', @_) }
288 0     0 1   sub appflow { shift->_execute('appflow', @_) }
289 0     0 1   sub appintegrations { shift->_execute('appintegrations', @_) }
290 0     0 1   sub application_autoscaling { shift->_execute('application-autoscaling', @_) }
291 0     0 1   sub application_insights { shift->_execute('application-insights', @_) }
292 0     0 1   sub applicationcostprofiler { shift->_execute('applicationcostprofiler', @_) }
293 0     0 1   sub appmesh { shift->_execute('appmesh', @_) }
294 0     0 1   sub apprunner { shift->_execute('apprunner', @_) }
295 0     0 1   sub appstream { shift->_execute('appstream', @_) }
296 0     0 1   sub appsync { shift->_execute('appsync', @_) }
297 0     0 1   sub arc_zonal_shift { shift->_execute('arc-zonal-shift', @_) }
298 0     0 1   sub athena { shift->_execute('athena', @_) }
299 0     0 1   sub auditmanager { shift->_execute('auditmanager', @_) }
300 0     0 1   sub autoscaling { shift->_execute('autoscaling', @_) }
301 0     0 1   sub autoscaling_plans { shift->_execute('autoscaling-plans', @_) }
302 0     0 1   sub backup { shift->_execute('backup', @_) }
303 0     0 1   sub backup_gateway { shift->_execute('backup-gateway', @_) }
304 0     0 1   sub backupstorage { shift->_execute('backupstorage', @_) }
305 0     0 1   sub batch { shift->_execute('batch', @_) }
306 0     0 1   sub billingconductor { shift->_execute('billingconductor', @_) }
307 0     0 1   sub braket { shift->_execute('braket', @_) }
308 0     0 1   sub budgets { shift->_execute('budgets', @_) }
309 0     0 1   sub ce { shift->_execute('ce', @_) }
310 0     0 1   sub chime { shift->_execute('chime', @_) }
311 0     0 1   sub chime_sdk_identity { shift->_execute('chime-sdk-identity', @_) }
312 0     0 1   sub chime_sdk_media_pipelines { shift->_execute('chime-sdk-media-pipelines', @_) }
313 0     0 1   sub chime_sdk_meetings { shift->_execute('chime-sdk-meetings', @_) }
314 0     0 1   sub chime_sdk_messaging { shift->_execute('chime-sdk-messaging', @_) }
315 0     0 1   sub chime_sdk_voice { shift->_execute('chime-sdk-voice', @_) }
316 0     0 1   sub cleanrooms { shift->_execute('cleanrooms', @_) }
317 0     0 1   sub cloud9 { shift->_execute('cloud9', @_) }
318 0     0 1   sub cloudcontrol { shift->_execute('cloudcontrol', @_) }
319 0     0 1   sub clouddirectory { shift->_execute('clouddirectory', @_) }
320 0     0 1   sub cloudformation { shift->_execute('cloudformation', @_) }
321 0     0 1   sub cloudfront { shift->_execute('cloudfront', @_) }
322 0     0 1   sub cloudhsm { shift->_execute('cloudhsm', @_) }
323 0     0 1   sub cloudhsmv2 { shift->_execute('cloudhsmv2', @_) }
324 0     0 1   sub cloudsearch { shift->_execute('cloudsearch', @_) }
325 0     0 1   sub cloudsearchdomain { shift->_execute('cloudsearchdomain', @_) }
326 0     0 1   sub cloudtrail { shift->_execute('cloudtrail', @_) }
327 0     0 1   sub cloudtrail_data { shift->_execute('cloudtrail-data', @_) }
328 0     0 1   sub cloudwatch { shift->_execute('cloudwatch', @_) }
329 0     0 1   sub codeartifact { shift->_execute('codeartifact', @_) }
330 0     0 1   sub codebuild { shift->_execute('codebuild', @_) }
331 0     0 1   sub codecatalyst { shift->_execute('codecatalyst', @_) }
332 0     0 1   sub codecommit { shift->_execute('codecommit', @_) }
333 0     0 1   sub codeguru_reviewer { shift->_execute('codeguru-reviewer', @_) }
334 0     0 1   sub codeguruprofiler { shift->_execute('codeguruprofiler', @_) }
335 0     0 1   sub codepipeline { shift->_execute('codepipeline', @_) }
336 0     0 1   sub codestar { shift->_execute('codestar', @_) }
337 0     0 1   sub codestar_connections { shift->_execute('codestar-connections', @_) }
338 0     0 1   sub codestar_notifications { shift->_execute('codestar-notifications', @_) }
339 0     0 1   sub cognito_identity { shift->_execute('cognito-identity', @_) }
340 0     0 1   sub cognito_idp { shift->_execute('cognito-idp', @_) }
341 0     0 1   sub cognito_sync { shift->_execute('cognito-sync', @_) }
342 0     0 1   sub comprehend { shift->_execute('comprehend', @_) }
343 0     0 1   sub comprehendmedical { shift->_execute('comprehendmedical', @_) }
344 0     0 1   sub compute_optimizer { shift->_execute('compute-optimizer', @_) }
345 0     0 1   sub configservice { shift->_execute('configservice', @_) }
346 0     0 1   sub configure { shift->_execute('configure', @_) }
347 0     0 1   sub connect { shift->_execute('connect', @_) }
348 0     0 1   sub connect_contact_lens { shift->_execute('connect-contact-lens', @_) }
349 0     0 1   sub connectcampaigns { shift->_execute('connectcampaigns', @_) }
350 0     0 1   sub connectcases { shift->_execute('connectcases', @_) }
351 0     0 1   sub connectparticipant { shift->_execute('connectparticipant', @_) }
352 0     0 1   sub controltower { shift->_execute('controltower', @_) }
353 0     0 1   sub cur { shift->_execute('cur', @_) }
354 0     0 1   sub customer_profiles { shift->_execute('customer-profiles', @_) }
355 0     0 1   sub databrew { shift->_execute('databrew', @_) }
356 0     0 1   sub dataexchange { shift->_execute('dataexchange', @_) }
357 0     0 1   sub datapipeline { shift->_execute('datapipeline', @_) }
358 0     0 1   sub datasync { shift->_execute('datasync', @_) }
359 0     0 1   sub dax { shift->_execute('dax', @_) }
360 0     0 1   sub deploy { shift->_execute('deploy', @_) }
361 0     0 1   sub detective { shift->_execute('detective', @_) }
362 0     0 1   sub devicefarm { shift->_execute('devicefarm', @_) }
363 0     0 1   sub devops_guru { shift->_execute('devops-guru', @_) }
364 0     0 1   sub directconnect { shift->_execute('directconnect', @_) }
365 0     0 1   sub discovery { shift->_execute('discovery', @_) }
366 0     0 1   sub dlm { shift->_execute('dlm', @_) }
367 0     0 1   sub dms { shift->_execute('dms', @_) }
368 0     0 1   sub docdb { shift->_execute('docdb', @_) }
369 0     0 1   sub docdb_elastic { shift->_execute('docdb-elastic', @_) }
370 0     0 1   sub drs { shift->_execute('drs', @_) }
371 0     0 1   sub ds { shift->_execute('ds', @_) }
372 0     0 1   sub dynamodb { shift->_execute('dynamodb', @_) }
373 0     0 1   sub dynamodbstreams { shift->_execute('dynamodbstreams', @_) }
374 0     0 1   sub ebs { shift->_execute('ebs', @_) }
375 0     0 1   sub ec2 { shift->_execute('ec2', @_) }
376 0     0 1   sub ec2_instance_connect { shift->_execute('ec2-instance-connect', @_) }
377 0     0 1   sub ecr { shift->_execute('ecr', @_) }
378 0     0 1   sub ecr_public { shift->_execute('ecr-public', @_) }
379 0     0 1   sub ecs { shift->_execute('ecs', @_) }
380 0     0 1   sub efs { shift->_execute('efs', @_) }
381 0     0 1   sub eks { shift->_execute('eks', @_) }
382 0     0 1   sub elastic_inference { shift->_execute('elastic-inference', @_) }
383 0     0 1   sub elasticache { shift->_execute('elasticache', @_) }
384 0     0 1   sub elasticbeanstalk { shift->_execute('elasticbeanstalk', @_) }
385 0     0 1   sub elastictranscoder { shift->_execute('elastictranscoder', @_) }
386 0     0 1   sub elb { shift->_execute('elb', @_) }
387 0     0 1   sub elbv2 { shift->_execute('elbv2', @_) }
388 0     0 1   sub emr { shift->_execute('emr', @_) }
389 0     0 1   sub emr_containers { shift->_execute('emr-containers', @_) }
390 0     0 1   sub emr_serverless { shift->_execute('emr-serverless', @_) }
391 0     0 1   sub es { shift->_execute('es', @_) }
392 0     0 1   sub events { shift->_execute('events', @_) }
393 0     0 1   sub evidently { shift->_execute('evidently', @_) }
394 0     0 1   sub finspace { shift->_execute('finspace', @_) }
395 0     0 1   sub finspace_data { shift->_execute('finspace-data', @_) }
396 0     0 1   sub firehose { shift->_execute('firehose', @_) }
397 0     0 1   sub fis { shift->_execute('fis', @_) }
398 0     0 1   sub fms { shift->_execute('fms', @_) }
399 0     0 1   sub forecast { shift->_execute('forecast', @_) }
400 0     0 1   sub forecastquery { shift->_execute('forecastquery', @_) }
401 0     0 1   sub frauddetector { shift->_execute('frauddetector', @_) }
402 0     0 1   sub fsx { shift->_execute('fsx', @_) }
403 0     0 1   sub gamelift { shift->_execute('gamelift', @_) }
404 0     0 1   sub gamesparks { shift->_execute('gamesparks', @_) }
405 0     0 1   sub glacier { shift->_execute('glacier', @_) }
406 0     0 1   sub globalaccelerator { shift->_execute('globalaccelerator', @_) }
407 0     0 1   sub glue { shift->_execute('glue', @_) }
408 0     0 1   sub grafana { shift->_execute('grafana', @_) }
409 0     0 1   sub greengrass { shift->_execute('greengrass', @_) }
410 0     0 1   sub greengrassv2 { shift->_execute('greengrassv2', @_) }
411 0     0 1   sub groundstation { shift->_execute('groundstation', @_) }
412 0     0 1   sub guardduty { shift->_execute('guardduty', @_) }
413 0     0 1   sub health { shift->_execute('health', @_) }
414 0     0 1   sub healthlake { shift->_execute('healthlake', @_) }
415 0     0 1   sub history { shift->_execute('history', @_) }
416 0     0 1   sub honeycode { shift->_execute('honeycode', @_) }
417 0     0 1   sub iam { shift->_execute('iam', @_) }
418 0     0 1   sub identitystore { shift->_execute('identitystore', @_) }
419 0     0 1   sub imagebuilder { shift->_execute('imagebuilder', @_) }
420 0     0 1   sub importexport { shift->_execute('importexport', @_) }
421 0     0 1   sub inspector { shift->_execute('inspector', @_) }
422 0     0 1   sub inspector2 { shift->_execute('inspector2', @_) }
423 0     0 1   sub internetmonitor { shift->_execute('internetmonitor', @_) }
424 0     0 1   sub iot { shift->_execute('iot', @_) }
425 0     0 1   sub iot_data { shift->_execute('iot-data', @_) }
426 0     0 1   sub iot_jobs_data { shift->_execute('iot-jobs-data', @_) }
427 0     0 1   sub iot_roborunner { shift->_execute('iot-roborunner', @_) }
428 0     0 1   sub iot1click_devices { shift->_execute('iot1click-devices', @_) }
429 0     0 1   sub iot1click_projects { shift->_execute('iot1click-projects', @_) }
430 0     0 1   sub iotanalytics { shift->_execute('iotanalytics', @_) }
431 0     0 1   sub iotdeviceadvisor { shift->_execute('iotdeviceadvisor', @_) }
432 0     0 1   sub iotevents { shift->_execute('iotevents', @_) }
433 0     0 1   sub iotevents_data { shift->_execute('iotevents-data', @_) }
434 0     0 1   sub iotfleethub { shift->_execute('iotfleethub', @_) }
435 0     0 1   sub iotfleetwise { shift->_execute('iotfleetwise', @_) }
436 0     0 1   sub iotsecuretunneling { shift->_execute('iotsecuretunneling', @_) }
437 0     0 1   sub iotsitewise { shift->_execute('iotsitewise', @_) }
438 0     0 1   sub iotthingsgraph { shift->_execute('iotthingsgraph', @_) }
439 0     0 1   sub iottwinmaker { shift->_execute('iottwinmaker', @_) }
440 0     0 1   sub iotwireless { shift->_execute('iotwireless', @_) }
441 0     0 1   sub ivs { shift->_execute('ivs', @_) }
442 0     0 1   sub ivschat { shift->_execute('ivschat', @_) }
443 0     0 1   sub kafka { shift->_execute('kafka', @_) }
444 0     0 1   sub kafkaconnect { shift->_execute('kafkaconnect', @_) }
445 0     0 1   sub kendra { shift->_execute('kendra', @_) }
446 0     0 1   sub kendra_ranking { shift->_execute('kendra-ranking', @_) }
447 0     0 1   sub keyspaces { shift->_execute('keyspaces', @_) }
448 0     0 1   sub kinesis { shift->_execute('kinesis', @_) }
449 0     0 1   sub kinesis_video_archived_media { shift->_execute('kinesis-video-archived-media', @_) }
450 0     0 1   sub kinesis_video_media { shift->_execute('kinesis-video-media', @_) }
451 0     0 1   sub kinesis_video_signaling { shift->_execute('kinesis-video-signaling', @_) }
452 0     0 1   sub kinesis_video_webrtc_storage { shift->_execute('kinesis-video-webrtc-storage', @_) }
453 0     0 1   sub kinesisanalytics { shift->_execute('kinesisanalytics', @_) }
454 0     0 1   sub kinesisanalyticsv2 { shift->_execute('kinesisanalyticsv2', @_) }
455 0     0 1   sub kinesisvideo { shift->_execute('kinesisvideo', @_) }
456 0     0 1   sub kms { shift->_execute('kms', @_) }
457 0     0 1   sub lakeformation { shift->_execute('lakeformation', @_) }
458 0     0 1   sub lambda { shift->_execute('lambda', @_) }
459 0     0 1   sub lex_models { shift->_execute('lex-models', @_) }
460 0     0 1   sub lex_runtime { shift->_execute('lex-runtime', @_) }
461 0     0 1   sub lexv2_models { shift->_execute('lexv2-models', @_) }
462 0     0 1   sub lexv2_runtime { shift->_execute('lexv2-runtime', @_) }
463 0     0 1   sub license_manager { shift->_execute('license-manager', @_) }
464 0     0 1   sub license_manager_linux_subscriptions { shift->_execute('license-manager-linux-subscriptions', @_) }
465 0     0 1   sub license_manager_user_subscriptions { shift->_execute('license-manager-user-subscriptions', @_) }
466 0     0 1   sub lightsail { shift->_execute('lightsail', @_) }
467 0     0 1   sub location { shift->_execute('location', @_) }
468 0     0 1   sub logs { shift->_execute('logs', @_) }
469 0     0 1   sub lookoutequipment { shift->_execute('lookoutequipment', @_) }
470 0     0 1   sub lookoutmetrics { shift->_execute('lookoutmetrics', @_) }
471 0     0 1   sub lookoutvision { shift->_execute('lookoutvision', @_) }
472 0     0 1   sub m2 { shift->_execute('m2', @_) }
473 0     0 1   sub machinelearning { shift->_execute('machinelearning', @_) }
474 0     0 1   sub macie { shift->_execute('macie', @_) }
475 0     0 1   sub macie2 { shift->_execute('macie2', @_) }
476 0     0 1   sub managedblockchain { shift->_execute('managedblockchain', @_) }
477 0     0 1   sub marketplace_catalog { shift->_execute('marketplace-catalog', @_) }
478 0     0 1   sub marketplace_entitlement { shift->_execute('marketplace-entitlement', @_) }
479 0     0 1   sub marketplacecommerceanalytics { shift->_execute('marketplacecommerceanalytics', @_) }
480 0     0 1   sub mediaconnect { shift->_execute('mediaconnect', @_) }
481 0     0 1   sub mediaconvert { shift->_execute('mediaconvert', @_) }
482 0     0 1   sub medialive { shift->_execute('medialive', @_) }
483 0     0 1   sub mediapackage { shift->_execute('mediapackage', @_) }
484 0     0 1   sub mediapackage_vod { shift->_execute('mediapackage-vod', @_) }
485 0     0 1   sub mediastore { shift->_execute('mediastore', @_) }
486 0     0 1   sub mediastore_data { shift->_execute('mediastore-data', @_) }
487 0     0 1   sub mediatailor { shift->_execute('mediatailor', @_) }
488 0     0 1   sub memorydb { shift->_execute('memorydb', @_) }
489 0     0 1   sub meteringmarketplace { shift->_execute('meteringmarketplace', @_) }
490 0     0 1   sub mgh { shift->_execute('mgh', @_) }
491 0     0 1   sub mgn { shift->_execute('mgn', @_) }
492 0     0 1   sub migration_hub_refactor_spaces { shift->_execute('migration-hub-refactor-spaces', @_) }
493 0     0 1   sub migrationhub_config { shift->_execute('migrationhub-config', @_) }
494 0     0 1   sub migrationhuborchestrator { shift->_execute('migrationhuborchestrator', @_) }
495 0     0 1   sub migrationhubstrategy { shift->_execute('migrationhubstrategy', @_) }
496 0     0 1   sub mobile { shift->_execute('mobile', @_) }
497 0     0 1   sub mq { shift->_execute('mq', @_) }
498 0     0 1   sub mturk { shift->_execute('mturk', @_) }
499 0     0 1   sub mwaa { shift->_execute('mwaa', @_) }
500 0     0 1   sub neptune { shift->_execute('neptune', @_) }
501 0     0 1   sub network_firewall { shift->_execute('network-firewall', @_) }
502 0     0 1   sub networkmanager { shift->_execute('networkmanager', @_) }
503 0     0 1   sub nimble { shift->_execute('nimble', @_) }
504 0     0 1   sub oam { shift->_execute('oam', @_) }
505 0     0 1   sub omics { shift->_execute('omics', @_) }
506 0     0 1   sub opensearch { shift->_execute('opensearch', @_) }
507 0     0 1   sub opensearchserverless { shift->_execute('opensearchserverless', @_) }
508 0     0 1   sub opsworks { shift->_execute('opsworks', @_) }
509 0     0 1   sub opsworks_cm { shift->_execute('opsworks-cm', @_) }
510 0     0 1   sub organizations { shift->_execute('organizations', @_) }
511 0     0 1   sub outposts { shift->_execute('outposts', @_) }
512 0     0 1   sub panorama { shift->_execute('panorama', @_) }
513 0     0 1   sub personalize { shift->_execute('personalize', @_) }
514 0     0 1   sub personalize_events { shift->_execute('personalize-events', @_) }
515 0     0 1   sub personalize_runtime { shift->_execute('personalize-runtime', @_) }
516 0     0 1   sub pi { shift->_execute('pi', @_) }
517 0     0 1   sub pinpoint { shift->_execute('pinpoint', @_) }
518 0     0 1   sub pinpoint_email { shift->_execute('pinpoint-email', @_) }
519 0     0 1   sub pinpoint_sms_voice { shift->_execute('pinpoint-sms-voice', @_) }
520 0     0 1   sub pinpoint_sms_voice_v2 { shift->_execute('pinpoint-sms-voice-v2', @_) }
521 0     0 1   sub pipes { shift->_execute('pipes', @_) }
522 0     0 1   sub polly { shift->_execute('polly', @_) }
523 0     0 1   sub pricing { shift->_execute('pricing', @_) }
524 0     0 1   sub privatenetworks { shift->_execute('privatenetworks', @_) }
525 0     0 1   sub proton { shift->_execute('proton', @_) }
526 0     0 1   sub qldb { shift->_execute('qldb', @_) }
527 0     0 1   sub qldb_session { shift->_execute('qldb-session', @_) }
528 0     0 1   sub quicksight { shift->_execute('quicksight', @_) }
529 0     0 1   sub ram { shift->_execute('ram', @_) }
530 0     0 1   sub rbin { shift->_execute('rbin', @_) }
531 0     0 1   sub rds { shift->_execute('rds', @_) }
532 0     0 1   sub rds_data { shift->_execute('rds-data', @_) }
533 0     0 1   sub redshift { shift->_execute('redshift', @_) }
534 0     0 1   sub redshift_data { shift->_execute('redshift-data', @_) }
535 0     0 1   sub redshift_serverless { shift->_execute('redshift-serverless', @_) }
536 0     0 1   sub rekognition { shift->_execute('rekognition', @_) }
537 0     0 1   sub resiliencehub { shift->_execute('resiliencehub', @_) }
538 0     0 1   sub resource_explorer_2 { shift->_execute('resource-explorer-2', @_) }
539 0     0 1   sub resource_groups { shift->_execute('resource-groups', @_) }
540 0     0 1   sub resourcegroupstaggingapi { shift->_execute('resourcegroupstaggingapi', @_) }
541 0     0 1   sub robomaker { shift->_execute('robomaker', @_) }
542 0     0 1   sub rolesanywhere { shift->_execute('rolesanywhere', @_) }
543 0     0 1   sub route53 { shift->_execute('route53', @_) }
544 0     0 1   sub route53_recovery_cluster { shift->_execute('route53-recovery-cluster', @_) }
545 0     0 1   sub route53_recovery_control_config { shift->_execute('route53-recovery-control-config', @_) }
546 0     0 1   sub route53_recovery_readiness { shift->_execute('route53-recovery-readiness', @_) }
547 0     0 1   sub route53domains { shift->_execute('route53domains', @_) }
548 0     0 1   sub route53resolver { shift->_execute('route53resolver', @_) }
549 0     0 1   sub rum { shift->_execute('rum', @_) }
550 0     0 1   sub s3 { shift->_execute('s3', @_) }
551 0     0 1   sub s3api { shift->_execute('s3api', @_) }
552 0     0 1   sub s3control { shift->_execute('s3control', @_) }
553 0     0 1   sub s3outposts { shift->_execute('s3outposts', @_) }
554 0     0 1   sub sagemaker { shift->_execute('sagemaker', @_) }
555 0     0 1   sub sagemaker_a2i_runtime { shift->_execute('sagemaker-a2i-runtime', @_) }
556 0     0 1   sub sagemaker_edge { shift->_execute('sagemaker-edge', @_) }
557 0     0 1   sub sagemaker_featurestore_runtime { shift->_execute('sagemaker-featurestore-runtime', @_) }
558 0     0 1   sub sagemaker_geospatial { shift->_execute('sagemaker-geospatial', @_) }
559 0     0 1   sub sagemaker_metrics { shift->_execute('sagemaker-metrics', @_) }
560 0     0 1   sub sagemaker_runtime { shift->_execute('sagemaker-runtime', @_) }
561 0     0 1   sub savingsplans { shift->_execute('savingsplans', @_) }
562 0     0 1   sub scheduler { shift->_execute('scheduler', @_) }
563 0     0 1   sub schemas { shift->_execute('schemas', @_) }
564 0     0 1   sub sdb { shift->_execute('sdb', @_) }
565 0     0 1   sub secretsmanager { shift->_execute('secretsmanager', @_) }
566 0     0 1   sub securityhub { shift->_execute('securityhub', @_) }
567 0     0 1   sub securitylake { shift->_execute('securitylake', @_) }
568 0     0 1   sub serverlessrepo { shift->_execute('serverlessrepo', @_) }
569 0     0 1   sub service_quotas { shift->_execute('service-quotas', @_) }
570 0     0 1   sub servicecatalog { shift->_execute('servicecatalog', @_) }
571 0     0 1   sub servicecatalog_appregistry { shift->_execute('servicecatalog-appregistry', @_) }
572 0     0 1   sub servicediscovery { shift->_execute('servicediscovery', @_) }
573 0     0 1   sub ses { shift->_execute('ses', @_) }
574 0     0 1   sub sesv2 { shift->_execute('sesv2', @_) }
575 0     0 1   sub shield { shift->_execute('shield', @_) }
576 0     0 1   sub signer { shift->_execute('signer', @_) }
577 0     0 1   sub simspaceweaver { shift->_execute('simspaceweaver', @_) }
578 0     0 1   sub sms { shift->_execute('sms', @_) }
579 0     0 1   sub snow_device_management { shift->_execute('snow-device-management', @_) }
580 0     0 1   sub snowball { shift->_execute('snowball', @_) }
581 0     0 1   sub sns { shift->_execute('sns', @_) }
582 0     0 1   sub sqs { shift->_execute('sqs', @_) }
583 0     0 1   sub ssm { shift->_execute('ssm', @_) }
584 0     0 1   sub ssm_contacts { shift->_execute('ssm-contacts', @_) }
585 0     0 1   sub ssm_incidents { shift->_execute('ssm-incidents', @_) }
586 0     0 1   sub ssm_sap { shift->_execute('ssm-sap', @_) }
587 0     0 1   sub sso { shift->_execute('sso', @_) }
588 0     0 1   sub sso_admin { shift->_execute('sso-admin', @_) }
589 0     0 1   sub sso_oidc { shift->_execute('sso-oidc', @_) }
590 0     0 1   sub stepfunctions { shift->_execute('stepfunctions', @_) }
591 0     0 1   sub storagegateway { shift->_execute('storagegateway', @_) }
592 0     0 1   sub sts { shift->_execute('sts', @_) }
593 0     0 1   sub support { shift->_execute('support', @_) }
594 0     0 1   sub support_app { shift->_execute('support-app', @_) }
595 0     0 1   sub swf { shift->_execute('swf', @_) }
596 0     0 1   sub synthetics { shift->_execute('synthetics', @_) }
597 0     0 1   sub textract { shift->_execute('textract', @_) }
598 0     0 1   sub timestream_query { shift->_execute('timestream-query', @_) }
599 0     0 1   sub timestream_write { shift->_execute('timestream-write', @_) }
600 0     0 1   sub tnb { shift->_execute('tnb', @_) }
601 0     0 1   sub transcribe { shift->_execute('transcribe', @_) }
602 0     0 1   sub transfer { shift->_execute('transfer', @_) }
603 0     0 1   sub translate { shift->_execute('translate', @_) }
604 0     0 1   sub voice_id { shift->_execute('voice-id', @_) }
605 0     0 1   sub waf { shift->_execute('waf', @_) }
606 0     0 1   sub waf_regional { shift->_execute('waf-regional', @_) }
607 0     0 1   sub wafv2 { shift->_execute('wafv2', @_) }
608 0     0 1   sub wellarchitected { shift->_execute('wellarchitected', @_) }
609 0     0 1   sub wisdom { shift->_execute('wisdom', @_) }
610 0     0 1   sub workdocs { shift->_execute('workdocs', @_) }
611 0     0 1   sub worklink { shift->_execute('worklink', @_) }
612 0     0 1   sub workmail { shift->_execute('workmail', @_) }
613 0     0 1   sub workmailmessageflow { shift->_execute('workmailmessageflow', @_) }
614 0     0 1   sub workspaces { shift->_execute('workspaces', @_) }
615 0     0 1   sub workspaces_web { shift->_execute('workspaces-web', @_) }
616 0     0 1   sub xray { shift->_execute('xray', @_) }
617              
618             1;
619              
620             __END__