File Coverage

blib/lib/OpenStack/Client/Auth/v3.pm
Criterion Covered Total %
statement 51 53 96.2
branch 24 28 85.7
condition 9 13 69.2
subroutine 9 10 90.0
pod 0 7 0.0
total 93 111 83.7


line stmt bran cond sub pod time code
1             #
2             # Copyright (c) 2018 cPanel, L.L.C.
3             # All rights reserved.
4             # http://cpanel.net/
5             #
6             # Distributed under the terms of the MIT license. See the LICENSE file for
7             # further details.
8             #
9             package OpenStack::Client::Auth::v3;
10              
11 1     1   6 use strict;
  1         2  
  1         34  
12 1     1   5 use warnings;
  1         2  
  1         23  
13              
14 1     1   5 use OpenStack::Client ();
  1         1  
  1         803  
15              
16             sub new ($$%) {
17 15     15 0 73 my ($class, $endpoint, %args) = @_;
18              
19 15 100       51 die 'No OpenStack tenant name provided in "tenant"' unless defined $args{'tenant'};
20 14 100       42 die 'No OpenStack username provided in "username"' unless defined $args{'username'};
21 13 100       37 die 'No OpenStack password provided in "password"' unless defined $args{'password'};
22              
23 12   50     60 $args{'domain'} ||= 'default';
24              
25             my $client = OpenStack::Client->new($endpoint,
26             'package_ua' => $args{'package_ua'},
27             'package_request' => $args{'package_request'},
28 12         42 'package_response' => $args{'package_response'}
29             );
30              
31             my %request = (
32             'auth' => {
33             'identity' => {
34             'methods' => [qw(password)],
35             'password' => {
36             'user' => {
37             'name' => $args{'username'},
38             'password' => $args{'password'},
39             'domain' => {
40 12         84 'name' => $args{'domain'}
41             }
42             }
43             }
44             }
45             }
46             );
47              
48 12 50       33 $request{'auth'}->{'scope'} = $args{'scope'} if defined $args{'scope'};
49              
50 12         41 my $response = $client->request(
51             'method' => 'POST',
52             'path' => '/auth/tokens',
53             'body' => \%request
54             );
55              
56 12         195 my $body = $response->decode_json;
57              
58 12 100       34 unless (defined $response->header('X-Subject-Token')) {
59 1         22 die 'No token found in response headers';
60             }
61              
62 11 100       108 unless (defined $body->{'token'}) {
63 1         16 die 'No token found in response body';
64             }
65              
66 10 100       25 unless (defined $body->{'token'}->{'catalog'}) {
67 1         19 die 'No service catalog found in response body token';
68             }
69              
70             return bless {
71             'package_ua' => $args{'package_ua'},
72             'package_request' => $args{'package_request'},
73             'package_response' => $args{'package_response'},
74             'response' => $response,
75             'body' => $body,
76             'clients' => {},
77 9         110 'services' => $body->{'token'}->{'catalog'}
78             }, $class;
79             }
80              
81             sub body ($) {
82 0     0 0 0 shift->{'body'};
83             }
84              
85             sub response ($) {
86 1     1 0 603 shift->{'response'};
87             }
88              
89             sub access ($) {
90 1     1 0 3213 shift->{'body'}->{'access'};
91             }
92              
93             sub token ($) {
94 8     8 0 431 shift->{'response'}->header('X-Subject-Token');
95             }
96              
97             sub services ($) {
98 1     1 0 574 my ($self) = @_;
99              
100             my %types = map {
101 1         6 $_->{'type'} => 1
102 1         2 } @{$self->{'services'}};
  1         3  
103              
104 1         7 return sort keys %types;
105             }
106              
107             sub service ($$%) {
108 10     10 0 1110 my ($self, $type, %opts) = @_;
109              
110 10 100       30 if (defined $self->{'clients'}->{$type}) {
111 2         5 return $self->{'clients'}->{$type};
112             }
113              
114 8 100       18 if (defined $opts{'uri'}) {
115             return $self->{'clients'}->{$type} = OpenStack::Client->new($opts{'uri'},
116             'package_ua' => $self->{'package_ua'},
117             'package_request' => $self->{'package_request'},
118 1         8 'package_response' => $self->{'package_response'},
119             'token' => $self->token
120             );
121             }
122              
123 7   100     28 $opts{'endpoint'} ||= 'public';
124              
125 7 50       31 if ($opts{'endpoint'} !~ /^(?:public|internal|admin)$/) {
126 0         0 die 'Invalid endpoint type specified in "endpoint"';
127             }
128              
129 7         14 foreach my $service (@{$self->{'services'}}) {
  7         17  
130 7 100       51 next unless $type eq $service->{'type'};
131              
132 6         10 foreach my $endpoint (@{$service->{'endpoints'}}) {
  6         14  
133 9 50 66     25 next if defined $opts{'id'} && $endpoint->{'id'} ne $opts{'id'};
134 9 50 66     22 next if defined $opts{'region'} && $endpoint->{'region'} ne $opts{'region'};
135 9 100 66     39 next if defined $opts{'endpoint'} && $endpoint->{'interface'} ne $opts{'endpoint'};
136              
137             return $self->{'clients'}->{$type} = OpenStack::Client->new($endpoint->{'url'},
138             'package_ua' => $self->{'package_ua'},
139             'package_request' => $self->{'package_request'},
140 6         17 'package_response' => $self->{'package_response'},
141             'token' => $self->token
142             );
143             }
144             }
145              
146 1         10 die "No service type '$type' found";
147             }
148              
149             1;