Test Failed
Push — master ( 0dd195...65f1e8 )
by Mihail
01:55
created

Application::makeStructure()   B

Complexity

Conditions 9
Paths 10

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
cc 9
eloc 5
nc 10
nop 2
dl 0
loc 6
ccs 0
cts 0
cp 0
crap 90
rs 8.0555
c 0
b 0
f 0
1
<?php
2
3
namespace Deploid;
4
5
use Symfony\Component\Console\Application as ConsoleApplication;
6
use Psr\Log\LoggerAwareInterface;
7
use Psr\Log\LoggerInterface;
8
use Symfony\Component\Process\Process;
9
10
class Application extends ConsoleApplication implements LoggerAwareInterface {
11
12
	/** @var string */
13
	private $releaseNameFormat = 'Y-m-d_H-i-s';
14
15
	/** @var array */
16
	private $structure = [
17
		'dirs' => [
18
			'releases',
19
			'releases/first',
20
			'shared',
21
		],
22
		'files' => [
23
			'deploid.log',
24
		],
25
		'links' => [
26
			'current:releases/first',
27
		],
28
	];
29
30
	/** @var LoggerInterface */
31
	private $logger;
32
33
	/* mutators */
34
35
	public function getReleaseNameFormat() {
36
		return $this->releaseNameFormat;
37
	}
38
39
	public function setReleaseNameFormat($releaseNameFormat) {
40
		$this->releaseNameFormat = $releaseNameFormat;
41
	}
42
43
	/**
44
	 * @return LoggerInterface
45
	 */
46
	public function getLogger() {
47
		return $this->logger;
48
	}
49
50
	/**
51
	 * @param LoggerInterface $logger
52
	 * @return void
53
	 */
54
	public function setLogger(LoggerInterface $logger) {
55
		$this->logger = $logger;
56
	}
57
58
	public function getStructure() {
59
		return $this->structure;
60
	}
61
62
	public function setStructure(array $structure) {
63
		$this->structure = $structure;
64
	}
65
66
	/* tools */
67
68
	/**
69
	 * @param string $path
70
	 * @return \Deploid\Payload
71
	 */
72
	public function deploidStructureValidate($path) {
73
		$payload = new Payload();
74
75
		$path = $this->absolutePath($path, getcwd());
76
77
		$releasesDir = realpath($path) . DIRECTORY_SEPARATOR . 'releases';
78
		if (!is_dir($releasesDir)) {
79
			$payload->setType(Payload::STRUCTURE_VALIDATE_FAIL);
80
			$payload->setMessage('directory "' . $releasesDir . '" does not exist');
81
			$payload->setCode(255);
82
			return $payload;
83
		}
84
85
		$sharedDir = realpath($path) . DIRECTORY_SEPARATOR . 'shared';
86
		if (!is_dir($sharedDir)) {
87
			$payload->setType(Payload::STRUCTURE_VALIDATE_FAIL);
88
			$payload->setMessage('directory "' . $sharedDir . '" does not exist');
89
			$payload->setCode(255);
90
			return $payload;
91
		}
92
93 1
		$logFile = realpath($path) . DIRECTORY_SEPARATOR . 'deploid.log';
94 1
		if (!is_file($logFile)) {
95
			$payload->setType(Payload::STRUCTURE_VALIDATE_FAIL);
96 1
			$payload->setMessage('file "' . $logFile . '" does not exist');
97
			$payload->setCode(255);
98
			return $payload;
99
		}
100
101
		$payload->setType(Payload::STRUCTURE_VALIDATE_SUCCESS);
102
		$payload->setMessage('structure is valid');
103 1
		$payload->setCode(0);
104 1
		return $payload;
105
	}
106 1
107 1
	/**
108 1
	 * @param string $path
109 1
	 * @return \Deploid\Payload
110
	 */
111
	public function deploidStructureInit($path) {
112
		$payload = new Payload();
113
114
		if (!strlen($path)) {
115 1
			$payload->setType(Payload::STRUCTURE_INIT_FAIL);
116
			$payload->setMessage('empty path');
117 1
			$payload->setCode(255);
118 1
			return $payload;
119 1
		}
120 1
121 1
		$path = $this->absolutePath($path, getcwd());
122
		$messages = [];
123
124
		if (!is_dir($path)) {
125
			if (mkdir($path, 0777, true)) {
126
				$messages[] = 'directory "' . realpath($path) . '" created';
127 1
			} else {
128
				$payload->setType(Payload::STRUCTURE_INIT_FAIL);
129 1
				$payload->setMessage('directory "' . $path . '" does not created');
130 1
				$payload->setCode(255);
131 1
				return $payload;
132 1
			}
133 1
		}
134
135
		$releasesDir = $path . DIRECTORY_SEPARATOR . 'releases';
136
		if (!is_dir($releasesDir)) {
137
			if (mkdir($releasesDir, 0777, true)) {
138
				$messages[] = 'directory "' . realpath($releasesDir) . '" created';
139 1
			} else {
140
				$payload->setType(Payload::STRUCTURE_INIT_FAIL);
141 1
				$payload->setMessage('directory "' . $releasesDir . '" does not created');
142 1
				$payload->setCode(255);
143 1
				return $payload;
144 1
			}
145 1
		}
146
147
		$sharedDir = $path . DIRECTORY_SEPARATOR . 'shared';
148
		if (!is_dir($sharedDir)) {
149
			if (mkdir($sharedDir, 0777, true)) {
150
				$messages[] = 'directory "' . realpath($sharedDir) . '" created';
151 1
			} else {
152
				$payload->setType(Payload::STRUCTURE_INIT_FAIL);
153 1
				$payload->setMessage('directory "' . $sharedDir . '" does not created');
154 1
				$payload->setCode(255);
155 1
				return $payload;
156 1
			}
157
		}
158
159
		$logFile = $path . DIRECTORY_SEPARATOR . 'deploid.log';
160
		if (!is_file($logFile)) {
161
			if (touch($logFile)) {
162
				$messages[] = 'file "' . realpath($logFile) . '" created';
163 1
			} else {
164 1
				$payload->setType(Payload::STRUCTURE_INIT_FAIL);
165
				$payload->setMessage('file"' . $logFile . '" does not created');
166 1
				$payload->setCode(255);
167
				return $payload;
168
			}
169
		}
170
171
		$payload->setType(Payload::STRUCTURE_INIT_SUCCESS);
172
		$payload->setMessage($messages);
173 1
		$payload->setCode(0);
174
		return $payload;
175 1
	}
176
177
	/**
178 1
	 * @param string $path
179 1
	 * @return \Deploid\Payload
180
	 */
181 1
	public function deploidStructureClean($path) {
182 1
		$payload = new Payload();
183 1
184 1
		if (!strlen($path)) {
185 1
			$payload->setType(Payload::STRUCTURE_CLEAN_FAIL);
186 1
			$payload->setMessage('empty path');
187 1
			$payload->setCode(255);
188
			return $payload;
189 1
		}
190 1
191 1
		$path = $this->absolutePath($path, getcwd());
192 1
193
		$paths = glob(realpath($path) . DIRECTORY_SEPARATOR . '*');
194
195
		$paths = array_filter($paths, function ($path) {
196
			return !in_array(basename($path), $this->structure['dirs'] + $this->structure['links'] + $this->structure['files']);
197
		});
198
199
		foreach ($paths as $pathname) {
200
			if (is_dir($pathname)) {
201
				rmdir($pathname);
202
			} else if (is_file($pathname)) {
203
				unlink($pathname);
204
			}
205
		}
206
207
		$payload->setType(Payload::STRUCTURE_CLEAN_SUCCESS);
208
		$payload->setMessage(array_merge(['cleaned items:'], $paths));
209
		$payload->setCode(0);
210
		return $payload;
211
	}
212
213
	/**
214
	 * @param string $release
215
	 * @param string $path
216
	 * @return \Deploid\Payload
217
	 */
218
	public function deploidReleaseExist($release, $path) {
219
		$payload = new Payload();
220
221
		if (!strlen($release)) {
222
			$payload->setType(Payload::RELEASE_EXIST_FAIL);
223
			$payload->setMessage('empty release name');
224
			$payload->setCode(255);
225
			return $payload;
226
		}
227
228
		if (!strlen($path)) {
229
			$payload->setType(Payload::RELEASE_EXIST_FAIL);
230
			$payload->setMessage('empty path');
231
			$payload->setCode(255);
232
			return $payload;
233
		}
234
235
		$path = $this->absolutePath($path, getcwd());
236
237
		$releaseDir = $path . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . $release;
238
		if (!is_dir($releaseDir)) {
239
			$payload->setType(Payload::RELEASE_EXIST_FAIL);
240
			$payload->setMessage('release "' . $release . '" does not exist');
241
			$payload->setCode(255);
242
			return $payload;
243
		}
244
245
		$payload->setType(Payload::RELEASE_EXIST_SUCCESS);
246
		$payload->setMessage('release "' . $release . '" exist');
247
		$payload->setCode(0);
248
		return $payload;
249
	}
250
251
	/**
252
	 * @param string $release
253
	 * @param string $path
254
	 * @return \Deploid\Payload
255
	 */
256
	public function deploidReleaseCreate($release, $path) {
257
		$payload = new Payload();
258
259
		if (!strlen($release)) {
260
			$payload->setType(Payload::RELEASE_CREATE_FAIL);
261
			$payload->setMessage('empty release name');
262
			$payload->setCode(255);
263
			return $payload;
264
		}
265
266
		if (!strlen($path)) {
267
			$payload->setType(Payload::RELEASE_CREATE_FAIL);
268
			$payload->setMessage('empty path');
269
			$payload->setCode(255);
270
			return $payload;
271
		}
272
273
		$path = $this->absolutePath($path, getcwd());
274
275
		$releaseDir = realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . $release;
276
277
		if (!mkdir($releaseDir, 0777, true)) {
278
			$payload->setType(Payload::RELEASE_CREATE_FAIL);
279
			$payload->setMessage('release "' . $release . '" does not created');
280
			$payload->setCode(255);
281
			return $payload;
282
		}
283
284
		$payload->setType(Payload::RELEASE_CREATE_SUCCESS);
285
		$payload->setMessage('release "' . $release . '" created');
286
		$payload->setCode(0);
287
		return $payload;
288
	}
289
290
	/**
291
	 * @param string $release
292
	 * @param string $path
293
	 * @return \Deploid\Payload
294
	 */
295
	public function deploidReleaseRemove($release, $path) {
296
		$payload = new Payload();
297
298
		if (!strlen($release)) {
299
			$payload->setType(Payload::RELEASE_REMOVE_FAIL);
300
			$payload->setMessage('empty release name');
301
			$payload->setCode(255);
302
			return $payload;
303
		}
304
305
		if (!strlen($path)) {
306
			$payload->setType(Payload::RELEASE_REMOVE_FAIL);
307
			$payload->setMessage('empty path');
308
			$payload->setCode(255);
309
			return $payload;
310
		}
311
312
		$path = $this->absolutePath($path, getcwd());
313
314
		$proccess = new Process('rm -r ' . realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . $release);
315
		$proccess->run();
316
317
		if (!$proccess->isSuccessful()) {
318
			$payload->setType(Payload::RELEASE_REMOVE_FAIL);
319
			$payload->setMessage($proccess->getErrorOutput());
320
			$payload->setCode($proccess->getExitCode());
321
			return $payload;
322
		}
323
324
		$payload->setType(Payload::RELEASE_REMOVE_SUCCESS);
325
		$payload->setMessage('release "' . ($release == '*' ? 'all' : $release) . '" removed');
326
		$payload->setCode(0);
327
		return $payload;
328
	}
329
330
	/**
331
	 * @param string $path
332
	 * @return \Deploid\Payload
333
	 */
334
	public function deploidReleaseList($path) {
335
		$payload = new Payload();
336
337
		if (!strlen($path)) {
338
			$payload->setType(Payload::RELEASE_LIST_FAIL);
339
			$payload->setMessage('path "' . $path . '" invalid');
340
			$payload->setCode(255);
341
			return $payload;
342
		}
343
344
		$path = $this->absolutePath($path, getcwd());
345
346
		$dirs = glob(realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR);
347
348
		if (empty($dirs)) {
349
			$payload->setType(Payload::RELEASE_LIST_FAIL);
350
			$payload->setMessage('release not found');
351
			$payload->setCode(0);
352
			return $payload;
353
		}
354
355
		$dirs = array_map(function ($path) {
356
			return basename($path);
357
		}, $dirs);
358
359
		$payload->setType(Payload::RELEASE_LIST_SUCCESS);
360
		$payload->setMessage($dirs);
361
		$payload->setCode(0);
362
		return $payload;
363
	}
364
365
	/**
366
	 * @param string $path
367
	 * @return \Deploid\Payload
368
	 */
369
	public function deploidReleaseLatest($path) {
370
		$payload = new Payload();
371
372
		if (!strlen($path)) {
373
			$payload->setType(Payload::RELEASE_LATEST_FAIL);
374
			$payload->setMessage('empty path');
375
			$payload->setCode(255);
376
			return $payload;
377
		}
378
379
		$path = $this->absolutePath($path, getcwd());
380
381
		$dirs = glob(realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR);
382
383
		if (empty($dirs)) {
384
			$payload->setType(Payload::RELEASE_LATEST_FAIL);
385
			$payload->setMessage('release not found');
386
			$payload->setCode(255);
387
			return $payload;
388
		}
389
390
		$dirs = array_map(function ($path) {
391
			return basename($path);
392
		}, $dirs);
393
394
		if (!rsort($dirs)) {
395
			$payload->setType(Payload::RELEASE_LATEST_FAIL);
396
			$payload->setMessage('fail sorted');
397
			$payload->setCode(255);
398
			return $payload;
399
		}
400
401
		$payload->setType(Payload::RELEASE_LATEST_SUCCESS);
402
		$payload->setMessage(current($dirs));
403
		$payload->setCode(0);
404
		return $payload;
405
	}
406
407
	/**
408
	 * @param string $path
409
	 * @return \Deploid\Payload
410
	 */
411
	public function deploidReleaseCurrent($path) {
412
		$payload = new Payload();
413
414
		if (!strlen($path)) {
415
			$payload->setType(Payload::RELEASE_CURRENT_FAIL);
416
			$payload->setMessage('empty path');
417
			$payload->setCode(255);
418
			return $payload;
419
		}
420
421
		$path = $this->absolutePath($path, getcwd());
422
423
		$link = realpath($path) . DIRECTORY_SEPARATOR . 'current';
424
425
		if (!file_exists($link)) {
426
			$payload->setType(Payload::RELEASE_CURRENT_FAIL);
427
			$payload->setMessage('current release does not exist');
428
			$payload->setCode(255);
429
			return $payload;
430
		}
431
432
		if (!is_link($link)) {
433
			$payload->setType(Payload::RELEASE_CURRENT_FAIL);
434
			$payload->setMessage('link to current release does not exist');
435
			$payload->setCode(255);
436
			return $payload;
437
		}
438
439
		$linkpath = readlink($link);
440
441
		if (!$linkpath) {
442
			$payload->setType(Payload::RELEASE_CURRENT_FAIL);
443
			$payload->setMessage('fail read link to current release');
444
			$payload->setCode(255);
445
			return $payload;
446
		}
447
448
		$payload->setType(Payload::RELEASE_CURRENT_SUCCESS);
449
		$payload->setMessage(basename($linkpath));
450
		$payload->setCode(0);
451
		return $payload;
452
	}
453
454
	/**
455
	 * @param string $release
456
	 * @param string $path
457
	 * @return \Deploid\Payload
458
	 */
459
	public function deploidReleaseSetup($release, $path) {
460
		$payload = new Payload();
461
462
		if (!strlen($path)) {
463
			$payload->setType(Payload::RELEASE_SETUP_FAIL);
464
			$payload->setMessage('path "' . $path . '" invalid');
465
			$payload->setCode(255);
466
			return $payload;
467
		}
468
469
		$path = $this->absolutePath($path, getcwd());
470
471
		$releaseDir = realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . $release;
472
		$currentDir = realpath($path) . DIRECTORY_SEPARATOR . 'current';
473
474
		$proccess = new Process('ln -sfn ' . $releaseDir . ' ' . $currentDir);
475
		$proccess->run();
476
477
		if (!$proccess->isSuccessful()) {
478
			$payload->setType(Payload::RELEASE_SETUP_FAIL);
479
			$payload->setMessage($proccess->getErrorOutput());
480
			$payload->setCode($proccess->getExitCode());
481
			return $payload;
482
		}
483
484
		$payload->setType(Payload::RELEASE_SETUP_SUCCESS);
485
		$payload->setMessage('release "' . $release . '" setup');
486
		$payload->setCode(0);
487
		return $payload;
488
	}
489
490
	/**
491
	 * @param int $quantity
492
	 * @param string $path
493
	 * @return \Deploid\Payload
494
	 */
495
	public function deploidReleaseRotate($quantity, $path) {
496
		$payload = new Payload();
497
498
		if (!$quantity || $quantity < 1) {
499
			$payload->setType(Payload::RELEASE_ROTATE_FAIL);
500
			$payload->setMessage('empty or invalid quantity');
501
			$payload->setCode(255);
502
			return $payload;
503
		}
504
505
		if (!strlen($path)) {
506
			$payload->setType(Payload::RELEASE_ROTATE_FAIL);
507
			$payload->setMessage('empty path');
508
			$payload->setCode(255);
509
			return $payload;
510
		}
511
512
		$path = $this->absolutePath($path, getcwd());
513
514
		$releases = glob(realpath($path) . DIRECTORY_SEPARATOR . 'releases' . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR);
515
516
		if (count($releases) <= $quantity) {
517
			$payload->setType(Payload::RELEASE_ROTATE_SUCCESS);
518
			$payload->setMessage('not found releases to rotate');
519
			$payload->setCode(0);
520
		}
521
522
		foreach (array_reverse($releases) as $idx => $release) {
523
			if ($idx <= ($quantity - 1)) continue;
524
			$proccess = new Process('rm -r ' . $release);
525
			$proccess->run();
526
		}
527
528
		$payload->setType(Payload::RELEASE_ROTATE_SUCCESS);
529
		$payload->setMessage('releases are rotated');
530
		$payload->setCode(0);
531
		return $payload;
532
	}
533
534
	public function absolutePath($path, $cwd) {
535
		if ($path[0] == '/') return $path;
536
		return $cwd . DIRECTORY_SEPARATOR . $path;
537
	}
538
539
	public function makeStructure($path, array $structure) {
540
		foreach ($structure as $sections) {
541
			foreach ($sections as $section => $item) {
542
				if ($section == 'dirs' && strlen($item)) mkdir($path . DIRECTORY_SEPARATOR . $item, 0777, true);
543
				if ($section == 'files' && strlen($item)) touch($path . DIRECTORY_SEPARATOR . $item);
544
				if ($section == 'links' && strlen($item)) link($path . DIRECTORY_SEPARATOR . explode(':', $item)[0], $path . DIRECTORY_SEPARATOR . explode(':', $item)[1]);
545
			}
546
		}
547
	}
548
549
}