1 <?php
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17
18 namespace OpenCloud\Common\Service;
19
20 use Guzzle\Http\ClientInterface;
21 use Guzzle\Http\Exception\BadResponseException;
22 use Guzzle\Http\Url;
23 use OpenCloud\Common\Base;
24 use OpenCloud\Common\Exceptions;
25 use OpenCloud\Common\Http\Message\Formatter;
26 use OpenCloud\OpenStack;
27 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
28
29 abstract class CatalogService extends AbstractService
30 {
31 const DEFAULT_URL_TYPE = 'publicURL';
32 const SUPPORTED_VERSION = null;
33
34 35 36
37 private $type;
38
39 40 41
42 private $name;
43
44 45 46
47 private $region;
48
49 50 51
52 private $urlType;
53
54 55 56 57
58 protected $regionless = false;
59
60 61 62 63 64 65 66 67 68 69 70 71 72 73
74 public function __construct(ClientInterface $client, $type = null, $name = null, $region = null, $urlType = null)
75 {
76 if (($client instanceof Base || $client instanceof OpenStack) && $client->hasLogger()) {
77 $this->setLogger($client->getLogger());
78 }
79
80 $this->setClient($client);
81
82 $this->name = $name ? : static::DEFAULT_NAME;
83 $this->region = $region;
84
85 $this->region = $region;
86 if ($this->regionless !== true && !$this->region) {
87 throw new Exceptions\ServiceException(sprintf(
88 'The %s service must have a region set. You can either pass in a region string as an argument param, or'
89 . ' set a default region for your user account by executing User::setDefaultRegion and ::update().',
90 $this->name
91 ));
92 }
93
94 $this->type = $type ? : static::DEFAULT_TYPE;
95 $this->urlType = $urlType ? : static::DEFAULT_URL_TYPE;
96 $this->setEndpoint($this->findEndpoint());
97
98 $this->client->setBaseUrl($this->getBaseUrl());
99
100 if ($this instanceof EventSubscriberInterface) {
101 $this->client->getEventDispatcher()->addSubscriber($this);
102 }
103 }
104
105 106 107
108 public function getType()
109 {
110 return $this->type;
111 }
112
113 114 115
116 public function getRegion()
117 {
118 return $this->region;
119 }
120
121 122 123
124 public function getName()
125 {
126 return $this->name;
127 }
128
129 130 131
132 public function getUrlType()
133 {
134 return $this->urlType;
135 }
136
137 138 139
140 public function region()
141 {
142 return $this->getRegion();
143 }
144
145 146 147
148 public function name()
149 {
150 return $this->name;
151 }
152
153 154 155 156 157 158 159
160 public function getUrl($path = null, array $query = array())
161 {
162 return Url::factory($this->getBaseUrl())
163 ->addPath($path)
164 ->setQuery($query);
165 }
166
167 168 169
170 public function url($path = null, array $query = array())
171 {
172 return $this->getUrl($path, $query);
173 }
174
175 176 177 178 179 180
181 public function getExtensions()
182 {
183 $ext = $this->getMetaUrl('extensions');
184
185 return (is_object($ext) && isset($ext->extensions)) ? $ext->extensions : array();
186 }
187
188 189 190 191 192
193 public function limits()
194 {
195 $limits = $this->getMetaUrl('limits');
196
197 return (is_object($limits)) ? $limits->limits : array();
198 }
199
200 201 202 203 204 205 206
207 private function findEndpoint()
208 {
209 if (!$this->getClient()->getCatalog()) {
210 $this->getClient()->authenticate();
211 }
212
213 $catalog = $this->getClient()->getCatalog();
214
215
216 foreach ($catalog->getItems() as $service) {
217 if ($service->hasType($this->type) && $service->hasName($this->name)) {
218 return Endpoint::factory($service->getEndpointFromRegion($this->region), static::SUPPORTED_VERSION, $this->getClient());
219 }
220 }
221
222 throw new Exceptions\EndpointError(sprintf(
223 'No endpoints for service type [%s], name [%s], region [%s] and urlType [%s]',
224 $this->type,
225 $this->name,
226 $this->region,
227 $this->urlType
228 ));
229 }
230
231 232 233 234 235 236 237 238 239 240
241 private function getMetaUrl($resource)
242 {
243 $url = clone $this->getBaseUrl();
244 $url->addPath($resource);
245 try {
246 $response = $this->getClient()->get($url)->send();
247
248 return Formatter::decode($response);
249 } catch (BadResponseException $e) {
250
251 return array();
252
253 }
254 }
255
256 257 258 259 260
261 public function getBaseUrl()
262 {
263 $url = ($this->urlType == 'publicURL')
264 ? $this->endpoint->getPublicUrl()
265 : $this->endpoint->getPrivateUrl();
266
267 if ($url === null) {
268 throw new Exceptions\ServiceException(sprintf(
269 'The base %s could not be found. Perhaps the service '
270 . 'you are using requires a different URL type, or does '
271 . 'not support this region.',
272 $this->urlType
273 ));
274 }
275
276 return $url;
277 }
278 }
279