AddEvent::getBindVolume()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 0
dl 0
loc 13
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
namespace TheAentMachine\AentGeneric\Event;
4
5
use Safe\Exceptions\ArrayException;
6
use Safe\Exceptions\FilesystemException;
7
use Safe\Exceptions\StringsException;
8
use Symfony\Component\Console\Logger\ConsoleLogger;
9
use TheAentMachine\Aent\Event\Service\AbstractServiceAddEvent;
10
use TheAentMachine\Aent\Event\Service\Model\Environments;
11
use TheAentMachine\Aent\Event\Service\Model\ServiceState;
12
use TheAentMachine\Docker\ImageService;
13
use TheAentMachine\Prompt\Helper\ValidatorHelper;
14
use TheAentMachine\Service\Service;
15
use TheAentMachine\Service\Volume\BindVolume;
16
17
final class AddEvent extends AbstractServiceAddEvent
18
{
19
    /**
20
     * @param Environments $environments
21
     * @return ServiceState[]
22
     * @throws ArrayException
23
     * @throws FilesystemException
24
     * @throws StringsException
25
     */
26
    protected function createServices(Environments $environments): array
27
    {
28
        $image = $this->prompt->getPromptHelper()->getDockerHubImage();
29
        $this->output->writeln("\nAlright, I'm going to use $image!");
30
        $imageService = new ImageService(new ConsoleLogger($this->output));
31
        $imageService->pullIfNotAvailable($image);
32
        $service = new Service();
33
        $service->setImage($image);
34
        $serviceName = $this->prompt->getPromptHelper()->getServiceName();
35
        $service->setServiceName($serviceName);
36
        if ($environments->hasTestEnvironments() || $environments->hasProductionEnvironments()) {
37
            $service->setNeedBuild($this->getNeedBuild());
38
            if ($service->getNeedBuild()) {
39
                $service->addDockerfileCommand("FROM $image");
40
            }
41
        }
42
        $bindVolume = $this->getBindVolume();
43
        if (!empty($bindVolume)) {
44
            $service->addBindVolume('./' . $bindVolume->getSource(), $bindVolume->getTarget());
45
        }
46
        $ports = $imageService->getInternalPorts($image);
47
        if (!empty($ports)) {
48
            $this->prompt->printAltBlock("Generic: adding internal ports...");
49
            foreach ($ports as $port) {
50
                $service->addInternalPort($port);
51
                // Heuristic: anything with a port 80, 1080 or 8080 must be HTTP port...
52
                if (\in_array($port, [80, 1080, 8080], true)) {
53
                    $service->addVirtualHost($port);
54
                }
55
            }
56
        }
57
        $volumes = $imageService->getVolumes($image);
58
        if (!empty($volumes)) {
59
            $this->prompt->printAltBlock("Generic: adding named volumes...");
60
            foreach ($volumes as $volume) {
61
                $volumeName = $serviceName.'_'.\str_replace('/', '_', $volume);
62
                $service->addNamedVolume($volumeName, $volume);
63
            }
64
        }
65
        return [ new ServiceState($service, $service, $service) ];
66
    }
67
68
    /**
69
     * @return bool
70
     */
71
    private function getNeedBuild(): bool
72
    {
73
        $text = "\nIs the image buildable?";
74
        $helpText = "Not recommended for database image.";
75
        return $this->prompt->confirm($text, $helpText, null, true);
76
    }
77
78
    /**
79
     * @return null|BindVolume
80
     */
81
    private function getBindVolume(): ?BindVolume
82
    {
83
        $text = "\nIs this image used to run a source code?";
84
        $needBindVolume = $this->prompt->confirm($text, null, null, true);
85
        if ($needBindVolume) {
86
            $text = "\nImage <info>workspace</info>";
87
            $helpText = "Workspace is the default directory of the image. For instance, <info>/var/www/html</info> or <info>/usr/src/app</info>.";
88
            $target = $this->prompt->input($text, $helpText, null, true, ValidatorHelper::getAbsolutePathValidator()) ?? '';
89
            $text = "\n<info>Application directory</info> (relative to the project root directory)";
90
            $source = $this->prompt->input($text, $helpText, null, true, ValidatorHelper::getRelativePathValidator()) ?? '';
91
            return new BindVolume($source, $target);
92
        }
93
        return null;
94
    }
95
}
96