1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
<?php
namespace OpenStack\Common\Service;
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Middleware as GuzzleMiddleware;
use OpenStack\Common\Auth\ServiceUrlResolver;
use OpenStack\Common\Auth\Token;
use OpenStack\Common\Transport\HandlerStack;
use OpenStack\Common\Transport\Middleware;
use OpenStack\Common\Transport\Utils;
use OpenStack\Identity\v3\Service;
/**
* A Builder for easily creating OpenStack services.
*
* @package OpenStack\Common\Service
*/
class Builder_override extends Builder
{
private $globalOptions = [];
/**
* Defaults that will be applied to options if no values are provided by the user.
*
* @var array
*/
private $defaults = ['urlType' => 'publicURL'];
public function __construct(array $globalOptions = [])
{
$this->globalOptions = $globalOptions;
parent::__construct($globalOptions);
}
public function getOptions()
{
return $this->globalOptions;
}
public function setOptions($Options)
{
$this->globalOptions = $Options;
}
/**
* Internal method which resolves the API and Service classes for a service.
*
* @param string $serviceName The name of the service, e.g. Compute
* @param int $serviceVersion The major version of the service, e.g. 2
*
* @return array
*/
private function getClasses($serviceName, $serviceVersion)
{
$rootNamespace = sprintf("OpenStack\\%s\\v%d", $serviceName, $serviceVersion);
return [
sprintf("%s\\Api", $rootNamespace),
sprintf("%s\\Service", $rootNamespace),
];
}
/**
* This method will return an OpenStack service ready fully built and ready for use. There is
* some initial setup that may prohibit users from directly instantiating the service class
* directly - this setup includes the configuration of the HTTP client's base URL, and the
* attachment of an authentication handler.
*
* @param $serviceName The name of the service as it appears in the OpenStack\* namespace
* @param $serviceVersion The major version of the service
* @param array $serviceOptions The service-specific options to use
*
* @return \OpenStack\Common\Service\ServiceInterface
*
* @throws \Exception
*/
public function createService($serviceName, $serviceVersion, array $serviceOptions = [])
{
$options = $this->mergeOptions($serviceOptions);
$this->stockIdentityService($options);
$this->stockAuthHandler($options);
$this->stockHttpClient($options, $serviceName);
list($apiClass, $serviceClass) = $this->getClasses($serviceName, $serviceVersion);
return new $serviceClass($options['httpClient'], new $apiClass());
}
private function stockHttpClient(array &$options, $serviceName)
{
if (!isset($options['httpClient']) || !($options['httpClient'] instanceof ClientInterface)) {
if (strcasecmp($serviceName, 'identity') === 0) {
$baseUrl = $options['authUrl'];
$stack = $this->getStack($options['authHandler']);
} else {
list($token, $baseUrl) = $options['identityService']->authenticate($options);
$stack = $this->getStack($options['authHandler'], $token);
}
$this->addDebugMiddleware($options, $stack);
$options['httpClient'] = $this->httpClient($baseUrl, $stack);
}
}
/**
* @codeCoverageIgnore
*/
private function addDebugMiddleware(array $options, HandlerStack &$stack)
{
if (!empty($options['debugLog'])
&& !empty($options['logger'])
&& !empty($options['messageFormatter'])
) {
$stack->push(GuzzleMiddleware::log($options['logger'], $options['messageFormatter']));
}
}
private function stockIdentityService(array &$options)
{
if (!isset($options['identityService'])) {
$httpClient = $this->httpClient($options['authUrl'], HandlerStack::create());
$options['identityService'] = Service::factory($httpClient);
}
}
/**
* @param array $options
* @codeCoverageIgnore
*/
private function stockAuthHandler(array &$options)
{
if (!isset($options['authHandler'])) {
$options['authHandler'] = function () use ($options) {
return $options['identityService']->generateToken($options);
};
}
}
private function getStack(callable $authHandler, Token $token = null)
{
$stack = HandlerStack::create();
$stack->push(Middleware::authHandler($authHandler, $token));
return $stack;
}
private function httpClient($baseUrl, HandlerStack $stack)
{
return new Client([
'base_uri' => Utils::normalizeUrl($baseUrl),
'handler' => $stack,
]);
}
private function mergeOptions(array $serviceOptions)
{
$options = array_merge($this->defaults, $this->globalOptions, $serviceOptions);
if (!isset($options['authUrl'])) {
throw new \InvalidArgumentException('"authUrl" is a required option');
}
return $options;
}
}
|