1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Laravel\Forge\Servers\Providers; |
4
|
|
|
|
5
|
|
|
use Laravel\Forge\Server; |
6
|
|
|
use InvalidArgumentException; |
7
|
|
|
use Laravel\Forge\ApiProvider; |
8
|
|
|
|
9
|
|
|
abstract class Provider |
10
|
|
|
{ |
11
|
|
|
/** |
12
|
|
|
* @var \Laravel\Forge\ApiProvider |
13
|
|
|
*/ |
14
|
|
|
protected $api; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* @var array |
18
|
|
|
*/ |
19
|
|
|
protected $payload = []; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Create new server provider instance. |
23
|
|
|
* |
24
|
|
|
* @param \Laravel\Forge\ApiProvider $api |
25
|
|
|
*/ |
26
|
|
|
public function __construct(ApiProvider $api) |
27
|
|
|
{ |
28
|
|
|
$this->api = $api; |
29
|
|
|
$this->initProvider(); |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Initializes server provider. |
34
|
|
|
*/ |
35
|
|
|
protected function initProvider() |
36
|
|
|
{ |
37
|
|
|
$this->payload['provider'] = $this->provider(); |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Server provider name. |
42
|
|
|
* |
43
|
|
|
* @return string |
44
|
|
|
*/ |
45
|
|
|
public function provider() |
46
|
|
|
{ |
47
|
|
|
return 'abstract'; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Server provider regions list. |
52
|
|
|
* |
53
|
|
|
* @return array |
54
|
|
|
*/ |
55
|
|
|
public function regions() |
56
|
|
|
{ |
57
|
|
|
return []; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Server provider server sizes. |
62
|
|
|
* |
63
|
|
|
* @return array |
64
|
|
|
*/ |
65
|
|
|
public function sizes() |
66
|
|
|
{ |
67
|
|
|
return []; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Available PHP versions. |
72
|
|
|
* |
73
|
|
|
* @return array |
74
|
|
|
*/ |
75
|
|
|
public function phpVersions() |
76
|
|
|
{ |
77
|
|
|
return [56, 70, 71, 72, 73]; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Validates payload before sending to Forge API. |
82
|
|
|
* |
83
|
|
|
* @return bool|array |
84
|
|
|
*/ |
85
|
|
|
public function validate() |
86
|
|
|
{ |
87
|
|
|
return true; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Determines if given region is available at current provider. |
92
|
|
|
* |
93
|
|
|
* @param string $region |
94
|
|
|
* |
95
|
|
|
* @return bool |
96
|
|
|
*/ |
97
|
|
|
public function regionAvailable(string $region) |
98
|
|
|
{ |
99
|
|
|
return $this->resourceAvailable($this->regions(), $region); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Determines if given resource exists in resources list. |
104
|
|
|
* |
105
|
|
|
* @param array $resources |
106
|
|
|
* @param mixed $resource |
107
|
|
|
* |
108
|
|
|
* @return bool |
109
|
|
|
*/ |
110
|
|
|
protected function resourceAvailable(array $resources, $resource) |
111
|
|
|
{ |
112
|
|
|
return isset($resources[$resource]); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* Determines if given key exists in current payload. |
117
|
|
|
* |
118
|
|
|
* @param string $key |
119
|
|
|
* |
120
|
|
|
* @return bool |
121
|
|
|
*/ |
122
|
|
|
public function hasPayload(string $key): bool |
123
|
|
|
{ |
124
|
|
|
return !empty($this->payload[$key]); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Set credential ID to create server with. |
129
|
|
|
* |
130
|
|
|
* @param int $credentialId |
131
|
|
|
* |
132
|
|
|
* @return static |
133
|
|
|
*/ |
134
|
|
|
public function usingCredential(int $credentialId) |
135
|
|
|
{ |
136
|
|
|
$this->payload['credential_id'] = $credentialId; |
137
|
|
|
|
138
|
|
|
return $this; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Set new server name. |
143
|
|
|
* |
144
|
|
|
* @param string $name |
145
|
|
|
* |
146
|
|
|
* @return static |
147
|
|
|
*/ |
148
|
|
|
public function identifiedAs(string $name) |
149
|
|
|
{ |
150
|
|
|
$this->payload['name'] = $name; |
151
|
|
|
|
152
|
|
|
return $this; |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
/** |
156
|
|
|
* Set server size ID. |
157
|
|
|
* |
158
|
|
|
* @param int|string $sizeId |
159
|
|
|
* |
160
|
|
|
* @return static |
161
|
|
|
*/ |
162
|
|
|
public function withSizeId($sizeId) |
163
|
|
|
{ |
164
|
|
|
if (!is_numeric(ltrim($sizeId, 0))) { |
165
|
|
|
throw new InvalidArgumentException('Given server size ID is not valid'); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
$this->payload['size'] = (int) $sizeId; |
169
|
|
|
|
170
|
|
|
return $this; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* Set server region. |
175
|
|
|
* |
176
|
|
|
* @param string $region |
177
|
|
|
* |
178
|
|
|
* @return static |
179
|
|
|
*/ |
180
|
|
|
public function at(string $region) |
181
|
|
|
{ |
182
|
|
|
if (!$this->regionAvailable($region)) { |
183
|
|
|
throw new InvalidArgumentException('Given region is not supported by '.$this->provider().' provider.'); |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
$this->payload['region'] = $region; |
187
|
|
|
|
188
|
|
|
return $this; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* Set PHP version. |
193
|
|
|
* |
194
|
|
|
* @param int|string $version |
195
|
|
|
* |
196
|
|
|
* @return static |
197
|
|
|
*/ |
198
|
|
|
public function runningPhp($version) |
199
|
|
|
{ |
200
|
|
|
$phpVersion = intval(str_replace(['php', '.'], '', $version)); |
201
|
|
|
|
202
|
|
|
if (!in_array($phpVersion, $this->phpVersions())) { |
203
|
|
|
throw new InvalidArgumentException('PHP version "php'.$phpVersion.'" is not supported.'); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
$this->payload['php_version'] = 'php'.$phpVersion; |
207
|
|
|
|
208
|
|
|
return $this; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* Indicates that server should be provisioned with MariaDB instead of MySQL. |
213
|
|
|
* |
214
|
|
|
* @param string $database = 'forge' |
215
|
|
|
* |
216
|
|
|
* @return static |
217
|
|
|
*/ |
218
|
|
View Code Duplication |
public function withMariaDb(string $database = 'forge') |
|
|
|
|
219
|
|
|
{ |
220
|
|
|
$this->payload['mariadb'] = 1; |
221
|
|
|
$this->payload['database'] = $database; |
222
|
|
|
$this->payload['database_type'] = 'mariadb'; |
223
|
|
|
|
224
|
|
|
return $this; |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* Indicates that server should be provisioned with MySQL. |
229
|
|
|
* |
230
|
|
|
* @param string $database = 'forge' |
231
|
|
|
* |
232
|
|
|
* @return static |
233
|
|
|
*/ |
234
|
|
View Code Duplication |
public function withMysql(string $database = 'forge') |
|
|
|
|
235
|
|
|
{ |
236
|
|
|
$this->payload['mariadb'] = 0; |
237
|
|
|
$this->payload['database'] = $database; |
238
|
|
|
$this->payload['database_type'] = 'mysql'; |
239
|
|
|
|
240
|
|
|
return $this; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* Indicates that server should be provisioned with PostrgreSQL. |
245
|
|
|
* |
246
|
|
|
* @param string $database = 'forge' |
247
|
|
|
* |
248
|
|
|
* @return static |
249
|
|
|
*/ |
250
|
|
View Code Duplication |
public function withPostgres(string $database = 'forge') |
|
|
|
|
251
|
|
|
{ |
252
|
|
|
$this->payload['mariadb'] = 0; |
253
|
|
|
$this->payload['database'] = $database; |
254
|
|
|
$this->payload['database_type'] = 'postgres'; |
255
|
|
|
|
256
|
|
|
return $this; |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
/** |
260
|
|
|
* Indicates that server should be provisioned as load balancer. |
261
|
|
|
* |
262
|
|
|
* @param bool $install = true |
263
|
|
|
* |
264
|
|
|
* @deprecated since 1.3.1 |
265
|
|
|
* @see Provider::asNodeBalancer() |
266
|
|
|
* |
267
|
|
|
* @return static |
268
|
|
|
*/ |
269
|
|
|
public function asLoadBalancer(bool $install = true) |
270
|
|
|
{ |
271
|
|
|
return $this->asNodeBalancer($install); |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* Indicates that server should be provisioned as load balancer. |
276
|
|
|
* |
277
|
|
|
* @param bool $install = true |
278
|
|
|
* |
279
|
|
|
* @return static |
280
|
|
|
*/ |
281
|
|
|
public function asNodeBalancer(bool $install = true) |
282
|
|
|
{ |
283
|
|
|
return $this->togglePayload('node_balancer', $install); |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* Servers ID that the new server should be connected to. |
288
|
|
|
* |
289
|
|
|
* @param array $servers |
290
|
|
|
* |
291
|
|
|
* @return static |
292
|
|
|
*/ |
293
|
|
|
public function connectedTo(array $servers) |
294
|
|
|
{ |
295
|
|
|
$this->payload['network'] = $servers; |
296
|
|
|
|
297
|
|
|
return $this; |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
/** |
301
|
|
|
* Public IP address. |
302
|
|
|
* |
303
|
|
|
* @param string $ip |
304
|
|
|
* |
305
|
|
|
* @return static |
306
|
|
|
*/ |
307
|
|
|
public function usingPublicIp(string $ip) |
308
|
|
|
{ |
309
|
|
|
$this->payload['ip_address'] = $ip; |
310
|
|
|
|
311
|
|
|
return $this; |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* Private IP address. |
316
|
|
|
* |
317
|
|
|
* @param string $ip |
318
|
|
|
* |
319
|
|
|
* @return static |
320
|
|
|
*/ |
321
|
|
|
public function usingPrivateIp(string $ip) |
322
|
|
|
{ |
323
|
|
|
$this->payload['private_ip_address'] = $ip; |
324
|
|
|
|
325
|
|
|
return $this; |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
/** |
329
|
|
|
* Set recipe that should be run after provisioning. |
330
|
|
|
* |
331
|
|
|
* @param int $id |
332
|
|
|
* |
333
|
|
|
* @return static |
334
|
|
|
*/ |
335
|
|
|
public function withRecipe(int $id) |
336
|
|
|
{ |
337
|
|
|
$this->payload['recipe_id'] = $id; |
338
|
|
|
|
339
|
|
|
return $this; |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
/** |
343
|
|
|
* Create new server. |
344
|
|
|
* |
345
|
|
|
* @throws \GuzzleHttp\Exception\RequestException |
346
|
|
|
* @throws \InvalidArgumentException |
347
|
|
|
* |
348
|
|
|
* @return \Laravel\Forge\Server |
349
|
|
|
*/ |
350
|
|
|
public function save() |
351
|
|
|
{ |
352
|
|
|
$validationResult = $this->validate(); |
353
|
|
|
|
354
|
|
|
if ($validationResult !== true) { |
355
|
|
|
throw new InvalidArgumentException( |
356
|
|
|
'Some required parameters are missing: '.implode(', ', $validationResult) |
357
|
|
|
); |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
$response = $this->api->getClient()->request('POST', 'servers', [ |
361
|
|
|
'json' => $this->sortPayload(), |
362
|
|
|
]); |
363
|
|
|
|
364
|
|
|
return Server::createFromResponse($response, $this->api); |
365
|
|
|
} |
366
|
|
|
|
367
|
|
|
/** |
368
|
|
|
* Sort payload data by key name. |
369
|
|
|
* |
370
|
|
|
* @return array |
371
|
|
|
*/ |
372
|
|
|
protected function sortPayload(): array |
373
|
|
|
{ |
374
|
|
|
$payload = $this->payload; |
375
|
|
|
|
376
|
|
|
ksort($payload); |
377
|
|
|
|
378
|
|
|
return $payload; |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
/** |
382
|
|
|
* Toggle boolean payload key. |
383
|
|
|
* |
384
|
|
|
* @param string $key |
385
|
|
|
* @param bool $install |
386
|
|
|
* |
387
|
|
|
* @return static |
388
|
|
|
*/ |
389
|
|
|
protected function togglePayload(string $key, bool $install) |
390
|
|
|
{ |
391
|
|
|
if ($install === false && isset($this->payload[$key])) { |
392
|
|
|
unset($this->payload[$key]); |
393
|
|
|
} elseif ($install === true) { |
394
|
|
|
$this->payload[$key] = 1; |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
return $this; |
398
|
|
|
} |
399
|
|
|
} |
400
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.