File Coverage

blib/lib/OpenStack/Client/Auth/v3.pm
Criterion Covered Total %
statement 50 52 96.1
branch 22 26 84.6
condition 9 13 69.2
subroutine 9 10 90.0
pod 0 7 0.0
total 90 108 83.3


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