File Coverage

blib/lib/Net/Amazon/DirectConnect.pm
Criterion Covered Total %
statement 26 95 27.3
branch 0 44 0.0
condition 0 2 0.0
subroutine 9 18 50.0
pod 6 6 100.0
total 41 165 24.8


line stmt bran cond sub pod time code
1             package Net::Amazon::DirectConnect;
2              
3 1     1   1435 use 5.10.0;
  1         3  
4 1     1   4 use strict;
  1         1  
  1         21  
5 1     1   3 use warnings FATAL => 'all';
  1         6  
  1         34  
6              
7 1     1   4 use Carp;
  1         1  
  1         65  
8 1     1   3 use JSON;
  1         1  
  1         4  
9 1     1   607 use YAML::Tiny;
  1         4352  
  1         65  
10 1     1   659 use HTTP::Request;
  1         15927  
  1         29  
11 1     1   625 use LWP::UserAgent;
  1         15666  
  1         27  
12 1     1   447 use Net::Amazon::Signature::V4;
  1         345161  
  1         913  
13              
14             my $yaml = YAML::Tiny->read_string(do { local $/; <DATA> });
15             close(DATA);
16              
17             =head1 NAME
18              
19             Net::Amazon::DirectConnect - Perl interface to the Amazon DirectConnect API
20              
21             =head1 VERSION
22              
23             Version 0.13
24             DirectConnect API version 2012-10-25
25              
26             =cut
27              
28             our $VERSION = '0.13';
29              
30             =head1 SYNOPSIS
31              
32             use Net::Amazon::DirectConnect;
33              
34             my $dc = Net::Amazon::DirectConnect->new(
35             region => 'ap-southeast-2',
36             access_key_id => 'access key',
37             secret_key_id => 'secret key'
38             );
39             ...
40              
41             =head1 SUBROUTINES/METHODS
42              
43             =head2 new
44              
45             use Net::Amazon::DirectConnect;
46              
47             my $dc = Net::Amazon::DirectConnect->new(
48             region => 'ap-southeast-2',
49             access_key_id => 'access key',
50             secret_key_id => 'secret key'
51             );
52             ...
53              
54             =cut
55              
56             sub new {
57 0     0 1   my $self = bless {}, shift;
58 0 0         return unless @_ % 2 == 0;
59              
60 0           my %args = @_;
61              
62             my %defaults = (
63             region => 'us-west-1',
64             access_key_id => $ENV{AWS_ACCESS_KEY_ID},
65             secret_key_id => $ENV{AWS_SECRET_ACCESS_KEY},
66              
67 0           _ua => LWP::UserAgent->new(agent => __PACKAGE__ . '/' . $VERSION),
68             _yaml => $yaml,
69             );
70              
71 0           foreach (keys %defaults) {
72 0 0         $self->{$_} = exists $args{$_} ? $args{$_} : $defaults{$_};
73             }
74              
75 0           $self->{sig} = Net::Amazon::Signature::V4->new($self->{access_key_id}, $self->{secret_key_id}, $self->{region}, 'directconnect');
76              
77 0           return $self;
78             }
79              
80             =head2 action
81              
82             Perform action against the Amazon Direct Connect API. Actions are validated against an embedded copy of
83             DirectConnect-2012-10-25.yml for correctness before the call is made.
84              
85             # List connections
86             my $connections = $dc->action('DescribeConnections');
87              
88             foreach my $dxcon (@{$connections->{connections}}) {
89             say "$dxcon->{connectionId} -> $dxcon->{connectionName}";
90              
91             # List Virtual Interfaces
92             my $virtual_interfaces = $dc->action('DescribeVirtualInterfaces', connectionId => $dxcon->{connectionId});
93             foreach my $vif (@{$virtual_interfaces->{virtualInterfaces}}) {
94             say " $vif->{connectionId}";
95             }
96             }
97              
98             =cut
99              
100             sub action {
101 0     0 1   my $self = shift;
102 0           my $method = shift;
103 0 0         return unless @_ % 2 == 0;
104 0           my %args = @_;
105              
106 0           $self->_validate($method, \%args);
107              
108 0           my $response = $self->_request($method,
109             content => encode_json \%args
110             );
111              
112 0 0         return decode_json $response->content if $response->is_success;
113             }
114              
115             =head2 ua
116              
117             Get or set UserAgent object
118              
119             say ref($dc->ua);
120             my $ua = my $lwp = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 } );
121             $ua->proxy('https', 'http://127.0.0.1:8080');
122             $dc->ua($ua);
123              
124             =cut
125              
126             sub ua {
127 0 0   0 1   ( ref $_[1] ) ? shift->{_ua} = $_[1] : shift->{_ua};
128             }
129              
130             =head2 spec
131              
132             Get or set YAML::Tiny object
133              
134             say ref($dc->spec);
135             $dc->spec(YAML::Tiny->read('new-spec.yml'));
136              
137             =cut
138              
139             sub spec {
140 0 0   0 1   ( ref $_[1] ) ? shift->{_yaml} = $_[1] : shift->{_yaml}->[0];
141             }
142              
143             =head2 region
144              
145             Get or set AWS region
146              
147             $dc->region('ap-southeast-2');
148             say $dc->region;
149              
150             =cut
151              
152             sub region {
153 0     0 1   my $self = shift;
154              
155 0 0         if (exists $_[0]) {
156 0           $self->{region} = shift;
157 0           $self->{sig} = Net::Amazon::Signature::V4->new($self->{access_key_id}, $self->{secret_key_id}, $self->{region}, 'directconnect');
158             }
159              
160 0           return $self->{region};
161             }
162              
163             =head2 credentials
164              
165             Set AWS credentials
166              
167             $dc->credentials(
168             access_key_id => 'MY_ACCESS_KEY',
169             secret_key_id => 'MY_SECRET_KEY'
170             );
171              
172             =cut
173              
174             sub credentials {
175 0     0 1   my $self = shift;
176              
177 0 0         return unless @_ % 2 == 0;
178 0           my %args = @_;
179              
180 0           foreach (qw(access_key_id secret_key_id)) {
181 0           $self->{$_} = $args{$_};
182             }
183              
184 0           return 1;
185             }
186              
187             =head1 Internal subroutines
188              
189             =head2 _request
190              
191             Build and sign HTTP::Request object, return if successful or croak if error
192              
193             =cut
194              
195             sub _request {
196 0     0     my $self = shift;
197 0           my $operation = shift;
198 0 0         return unless @_ % 2 == 0;
199 0           my %args = @_;
200              
201 0 0         croak __PACKAGE__ . '->_request: Missing operation' unless $operation;
202 0 0         croak __PACKAGE__ . '->_request: Invalid or empty region' unless $self->{region};
203              
204 0           my $host = sprintf 'directconnect.%s.amazonaws.com/', $self->{region};
205             my $headers = [
206             Version => $self->spec->{api_version},
207             Host => $host,
208             Date => POSIX::strftime( '%Y%m%dT%H%M%SZ', gmtime ),
209             'Content-Type' => 'application/x-amz-json-1.1',
210             'X-Amz-Target' => $self->spec->{target_prefix} . $operation,
211 0 0         exists $args{headers} ? @{$args{headers}} : ()
  0            
212             ];
213              
214 0           my $req = HTTP::Request->new(POST => "https://$host", $headers);
215 0 0         $req->content($args{content}) if exists $args{content};
216              
217 0           $req = $self->{sig}->sign($req);
218              
219 0           my $response = $self->ua->request($req);
220 0 0         if (!$response->is_success) {
221              
222 0           my $content = eval { decode_json($response->content) };
  0            
223 0   0       $content ||= {};
224              
225 0           my $err_string = '';
226 0 0         $err_string .= $content->{__type} if $content->{__type};
227 0 0         $err_string .= ' ' . $content->{message} if $content->{message};
228 0 0         $err_string = $response->content unless $err_string;
229              
230 0           croak __PACKAGE__ . sprintf('->_request: %s', $err_string);
231             }
232              
233 0           return $response;
234             }
235              
236             =head2 _validate
237              
238             Validate the method and required arguments against the current version of the Direct Connect API (2012-10-25)
239              
240             =cut
241              
242             sub _validate {
243 0     0     my $self = shift;
244 0           my $method = shift;
245 0           my $args = shift;
246              
247 0           my ($spec) = grep { $_->{name} eq $method } @{$self->spec->{operations}};
  0            
  0            
248 0 0         return unless ref $spec;
249              
250             local *check_yaml = sub {
251 0     0     my $s = shift;
252 0           my $o = shift;
253              
254 0           foreach (keys %$s) {
255 0 0         if (grep /^required$/, @{$s->{$_}}) {
  0            
256 0 0         croak __PACKAGE__ . ": $method called without required field ($_)" unless exists $o->{$_};
257             }
258              
259 0 0         if (ref $s->{$_}->[0] eq 'HASH') {
260 0 0         return unless check_yaml($s->{$_}->[0]->{structure}, $o->{$_});
261             }
262             }
263              
264 0           return 1;
265 0           };
266              
267 0           return check_yaml($spec->{inputs}, $args);
268             }
269              
270             =head1 AUTHOR
271              
272             Cameron Daniel, C<< <cameron.daniel at megaport.com> >>
273              
274             =head1 SUPPORT
275              
276             You can find documentation for this module with the perldoc command or at https://github.com/megaport/p5-net-amazon-directconnect/
277              
278             perldoc Net::Amazon::DirectConnect
279              
280             =cut
281              
282             1;
283              
284             __DATA__
285             # Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
286             #
287             # Licensed under the Apache License, Version 2.0 (the "License"). You
288             # may not use this file except in compliance with the License. A copy of
289             # the License is located at
290             #
291             # http://aws.amazon.com/apache2.0/
292             #
293             # or in the "license" file accompanying this file. This file is
294             # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
295             # ANY KIND, either express or implied. See the License for the specific
296             # language governing permissions and limitations under the License.
297              
298             ---
299             json_version: '1.1'
300             target_prefix: OvertureService.
301             api_version: '2012-10-25'
302             operations:
303             - name: AllocateConnectionOnInterconnect
304             method: allocate_connection_on_interconnect
305             inputs:
306             bandwidth:
307             - string
308             - required
309             connectionName:
310             - string
311             - required
312             ownerAccount:
313             - string
314             - required
315             interconnectId:
316             - string
317             - required
318             vlan:
319             - integer
320             - required
321             outputs:
322             ownerAccount:
323             sym: owner_account
324             type: string
325             connectionId:
326             sym: connection_id
327             type: string
328             connectionName:
329             sym: connection_name
330             type: string
331             connectionState:
332             sym: connection_state
333             type: string
334             region:
335             sym: region
336             type: string
337             location:
338             sym: location
339             type: string
340             bandwidth:
341             sym: bandwidth
342             type: string
343             vlan:
344             sym: vlan
345             type: integer
346             partnerName:
347             sym: partner_name
348             type: string
349             - name: AllocatePrivateVirtualInterface
350             method: allocate_private_virtual_interface
351             inputs:
352             connectionId:
353             - string
354             - required
355             ownerAccount:
356             - string
357             - required
358             newPrivateVirtualInterfaceAllocation:
359             - structure:
360             virtualInterfaceName:
361             - string
362             - required
363             vlan:
364             - integer
365             - required
366             asn:
367             - integer
368             - required
369             authKey:
370             - string
371             amazonAddress:
372             - string
373             customerAddress:
374             - string
375             - required
376             outputs:
377             ownerAccount:
378             sym: owner_account
379             type: string
380             virtualInterfaceId:
381             sym: virtual_interface_id
382             type: string
383             location:
384             sym: location
385             type: string
386             connectionId:
387             sym: connection_id
388             type: string
389             virtualInterfaceType:
390             sym: virtual_interface_type
391             type: string
392             virtualInterfaceName:
393             sym: virtual_interface_name
394             type: string
395             vlan:
396             sym: vlan
397             type: integer
398             asn:
399             sym: asn
400             type: integer
401             authKey:
402             sym: auth_key
403             type: string
404             amazonAddress:
405             sym: amazon_address
406             type: string
407             customerAddress:
408             sym: customer_address
409             type: string
410             virtualInterfaceState:
411             sym: virtual_interface_state
412             type: string
413             customerRouterConfig:
414             sym: customer_router_config
415             type: string
416             virtualGatewayId:
417             sym: virtual_gateway_id
418             type: string
419             routeFilterPrefixes:
420             sym: route_filter_prefixes
421             type: hash
422             members:
423             cidr:
424             sym: cidr
425             type: string
426             - name: AllocatePublicVirtualInterface
427             method: allocate_public_virtual_interface
428             inputs:
429             connectionId:
430             - string
431             - required
432             ownerAccount:
433             - string
434             - required
435             newPublicVirtualInterfaceAllocation:
436             - structure:
437             virtualInterfaceName:
438             - string
439             - required
440             vlan:
441             - integer
442             - required
443             asn:
444             - integer
445             - required
446             authKey:
447             - string
448             amazonAddress:
449             - string
450             - required
451             customerAddress:
452             - string
453             - required
454             routeFilterPrefixes:
455             - list:
456             - structure:
457             cidr:
458             - string
459             - required
460             - required
461             outputs:
462             ownerAccount:
463             sym: owner_account
464             type: string
465             virtualInterfaceId:
466             sym: virtual_interface_id
467             type: string
468             location:
469             sym: location
470             type: string
471             connectionId:
472             sym: connection_id
473             type: string
474             virtualInterfaceType:
475             sym: virtual_interface_type
476             type: string
477             virtualInterfaceName:
478             sym: virtual_interface_name
479             type: string
480             vlan:
481             sym: vlan
482             type: integer
483             asn:
484             sym: asn
485             type: integer
486             authKey:
487             sym: auth_key
488             type: string
489             amazonAddress:
490             sym: amazon_address
491             type: string
492             customerAddress:
493             sym: customer_address
494             type: string
495             virtualInterfaceState:
496             sym: virtual_interface_state
497             type: string
498             customerRouterConfig:
499             sym: customer_router_config
500             type: string
501             virtualGatewayId:
502             sym: virtual_gateway_id
503             type: string
504             routeFilterPrefixes:
505             sym: route_filter_prefixes
506             type: hash
507             members:
508             cidr:
509             sym: cidr
510             type: string
511             - name: ConfirmConnection
512             method: confirm_connection
513             inputs:
514             connectionId:
515             - string
516             - required
517             outputs:
518             connectionState:
519             sym: connection_state
520             type: string
521             - name: ConfirmPrivateVirtualInterface
522             method: confirm_private_virtual_interface
523             inputs:
524             virtualInterfaceId:
525             - string
526             - required
527             virtualGatewayId:
528             - string
529             - required
530             outputs:
531             virtualInterfaceState:
532             sym: virtual_interface_state
533             type: string
534             - name: ConfirmPublicVirtualInterface
535             method: confirm_public_virtual_interface
536             inputs:
537             virtualInterfaceId:
538             - string
539             - required
540             outputs:
541             virtualInterfaceState:
542             sym: virtual_interface_state
543             type: string
544             - name: CreateConnection
545             method: create_connection
546             inputs:
547             location:
548             - string
549             - required
550             bandwidth:
551             - string
552             - required
553             connectionName:
554             - string
555             - required
556             outputs:
557             ownerAccount:
558             sym: owner_account
559             type: string
560             connectionId:
561             sym: connection_id
562             type: string
563             connectionName:
564             sym: connection_name
565             type: string
566             connectionState:
567             sym: connection_state
568             type: string
569             region:
570             sym: region
571             type: string
572             location:
573             sym: location
574             type: string
575             bandwidth:
576             sym: bandwidth
577             type: string
578             vlan:
579             sym: vlan
580             type: integer
581             partnerName:
582             sym: partner_name
583             type: string
584             - name: CreateInterconnect
585             method: create_interconnect
586             inputs:
587             interconnectName:
588             - string
589             - required
590             bandwidth:
591             - string
592             - required
593             location:
594             - string
595             - required
596             outputs:
597             interconnectId:
598             sym: interconnect_id
599             type: string
600             interconnectName:
601             sym: interconnect_name
602             type: string
603             interconnectState:
604             sym: interconnect_state
605             type: string
606             region:
607             sym: region
608             type: string
609             location:
610             sym: location
611             type: string
612             bandwidth:
613             sym: bandwidth
614             type: string
615             - name: CreatePrivateVirtualInterface
616             method: create_private_virtual_interface
617             inputs:
618             connectionId:
619             - string
620             - required
621             newPrivateVirtualInterface:
622             - structure:
623             virtualInterfaceName:
624             - string
625             - required
626             vlan:
627             - integer
628             - required
629             asn:
630             - integer
631             - required
632             authKey:
633             - string
634             amazonAddress:
635             - string
636             customerAddress:
637             - string
638             virtualGatewayId:
639             - string
640             - required
641             - required
642             outputs:
643             ownerAccount:
644             sym: owner_account
645             type: string
646             virtualInterfaceId:
647             sym: virtual_interface_id
648             type: string
649             location:
650             sym: location
651             type: string
652             connectionId:
653             sym: connection_id
654             type: string
655             virtualInterfaceType:
656             sym: virtual_interface_type
657             type: string
658             virtualInterfaceName:
659             sym: virtual_interface_name
660             type: string
661             vlan:
662             sym: vlan
663             type: integer
664             asn:
665             sym: asn
666             type: integer
667             authKey:
668             sym: auth_key
669             type: string
670             amazonAddress:
671             sym: amazon_address
672             type: string
673             customerAddress:
674             sym: customer_address
675             type: string
676             virtualInterfaceState:
677             sym: virtual_interface_state
678             type: string
679             customerRouterConfig:
680             sym: customer_router_config
681             type: string
682             virtualGatewayId:
683             sym: virtual_gateway_id
684             type: string
685             routeFilterPrefixes:
686             sym: route_filter_prefixes
687             type: hash
688             members:
689             cidr:
690             sym: cidr
691             type: string
692             - name: CreatePublicVirtualInterface
693             method: create_public_virtual_interface
694             inputs:
695             connectionId:
696             - string
697             - required
698             newPublicVirtualInterface:
699             - structure:
700             virtualInterfaceName:
701             - string
702             - required
703             vlan:
704             - integer
705             - required
706             asn:
707             - integer
708             - required
709             authKey:
710             - string
711             amazonAddress:
712             - string
713             - required
714             customerAddress:
715             - string
716             - required
717             routeFilterPrefixes:
718             - list:
719             - structure:
720             cidr:
721             - string
722             - required
723             - required
724             outputs:
725             ownerAccount:
726             sym: owner_account
727             type: string
728             virtualInterfaceId:
729             sym: virtual_interface_id
730             type: string
731             location:
732             sym: location
733             type: string
734             connectionId:
735             sym: connection_id
736             type: string
737             virtualInterfaceType:
738             sym: virtual_interface_type
739             type: string
740             virtualInterfaceName:
741             sym: virtual_interface_name
742             type: string
743             vlan:
744             sym: vlan
745             type: integer
746             asn:
747             sym: asn
748             type: integer
749             authKey:
750             sym: auth_key
751             type: string
752             amazonAddress:
753             sym: amazon_address
754             type: string
755             customerAddress:
756             sym: customer_address
757             type: string
758             virtualInterfaceState:
759             sym: virtual_interface_state
760             type: string
761             customerRouterConfig:
762             sym: customer_router_config
763             type: string
764             virtualGatewayId:
765             sym: virtual_gateway_id
766             type: string
767             routeFilterPrefixes:
768             sym: route_filter_prefixes
769             type: hash
770             members:
771             cidr:
772             sym: cidr
773             type: string
774             - name: DeleteConnection
775             method: delete_connection
776             inputs:
777             connectionId:
778             - string
779             - required
780             outputs:
781             ownerAccount:
782             sym: owner_account
783             type: string
784             connectionId:
785             sym: connection_id
786             type: string
787             connectionName:
788             sym: connection_name
789             type: string
790             connectionState:
791             sym: connection_state
792             type: string
793             region:
794             sym: region
795             type: string
796             location:
797             sym: location
798             type: string
799             bandwidth:
800             sym: bandwidth
801             type: string
802             vlan:
803             sym: vlan
804             type: integer
805             partnerName:
806             sym: partner_name
807             type: string
808             - name: DeleteInterconnect
809             method: delete_interconnect
810             inputs:
811             interconnectId:
812             - string
813             - required
814             outputs:
815             interconnectState:
816             sym: interconnect_state
817             type: string
818             - name: DeleteVirtualInterface
819             method: delete_virtual_interface
820             inputs:
821             virtualInterfaceId:
822             - string
823             - required
824             outputs:
825             virtualInterfaceState:
826             sym: virtual_interface_state
827             type: string
828             - name: DescribeConnections
829             method: describe_connections
830             inputs:
831             connectionId:
832             - string
833             outputs:
834             connections:
835             sym: connections
836             type: hash
837             members:
838             ownerAccount:
839             sym: owner_account
840             type: string
841             connectionId:
842             sym: connection_id
843             type: string
844             connectionName:
845             sym: connection_name
846             type: string
847             connectionState:
848             sym: connection_state
849             type: string
850             region:
851             sym: region
852             type: string
853             location:
854             sym: location
855             type: string
856             bandwidth:
857             sym: bandwidth
858             type: string
859             vlan:
860             sym: vlan
861             type: integer
862             partnerName:
863             sym: partner_name
864             type: string
865             - name: DescribeConnectionsOnInterconnect
866             method: describe_connections_on_interconnect
867             inputs:
868             interconnectId:
869             - string
870             - required
871             outputs:
872             connections:
873             sym: connections
874             type: hash
875             members:
876             ownerAccount:
877             sym: owner_account
878             type: string
879             connectionId:
880             sym: connection_id
881             type: string
882             connectionName:
883             sym: connection_name
884             type: string
885             connectionState:
886             sym: connection_state
887             type: string
888             region:
889             sym: region
890             type: string
891             location:
892             sym: location
893             type: string
894             bandwidth:
895             sym: bandwidth
896             type: string
897             vlan:
898             sym: vlan
899             type: integer
900             partnerName:
901             sym: partner_name
902             type: string
903             - name: DescribeInterconnects
904             method: describe_interconnects
905             inputs:
906             interconnectId:
907             - string
908             outputs:
909             interconnects:
910             sym: interconnects
911             type: hash
912             members:
913             interconnectId:
914             sym: interconnect_id
915             type: string
916             interconnectName:
917             sym: interconnect_name
918             type: string
919             interconnectState:
920             sym: interconnect_state
921             type: string
922             region:
923             sym: region
924             type: string
925             location:
926             sym: location
927             type: string
928             bandwidth:
929             sym: bandwidth
930             type: string
931             - name: DescribeLocations
932             method: describe_locations
933             inputs: {}
934             outputs:
935             locations:
936             sym: locations
937             type: hash
938             members:
939             locationCode:
940             sym: location_code
941             type: string
942             locationName:
943             sym: location_name
944             type: string
945             - name: DescribeVirtualGateways
946             method: describe_virtual_gateways
947             inputs: {}
948             outputs:
949             virtualGateways:
950             sym: virtual_gateways
951             type: hash
952             members:
953             virtualGatewayId:
954             sym: virtual_gateway_id
955             type: string
956             virtualGatewayState:
957             sym: virtual_gateway_state
958             type: string
959             - name: DescribeVirtualInterfaces
960             method: describe_virtual_interfaces
961             inputs:
962             connectionId:
963             - string
964             virtualInterfaceId:
965             - string
966             outputs:
967             virtualInterfaces:
968             sym: virtual_interfaces
969             type: hash
970             members:
971             ownerAccount:
972             sym: owner_account
973             type: string
974             virtualInterfaceId:
975             sym: virtual_interface_id
976             type: string
977             location:
978             sym: location
979             type: string
980             connectionId:
981             sym: connection_id
982             type: string
983             virtualInterfaceType:
984             sym: virtual_interface_type
985             type: string
986             virtualInterfaceName:
987             sym: virtual_interface_name
988             type: string
989             vlan:
990             sym: vlan
991             type: integer
992             asn:
993             sym: asn
994             type: integer
995             authKey:
996             sym: auth_key
997             type: string
998             amazonAddress:
999             sym: amazon_address
1000             type: string
1001             customerAddress:
1002             sym: customer_address
1003             type: string
1004             virtualInterfaceState:
1005             sym: virtual_interface_state
1006             type: string
1007             customerRouterConfig:
1008             sym: customer_router_config
1009             type: string
1010             virtualGatewayId:
1011             sym: virtual_gateway_id
1012             type: string
1013             routeFilterPrefixes:
1014             sym: route_filter_prefixes
1015             type: hash
1016             members:
1017             cidr:
1018             sym: cidr
1019             type: string