Passed
Push — master ( e47c8e...e58eed )
by Keoghan
07:56
created

Porter   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 224
Duplicated Lines 0 %

Test Coverage

Coverage 98.61%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 24
eloc 54
c 4
b 0
f 0
dl 0
loc 224
ccs 71
cts 72
cp 0.9861
rs 10

13 Methods

Rating   Name   Duplication   Size   Complexity  
A turnOffService() 0 12 3
A start() 0 9 4
A stop() 0 13 3
A restart() 0 8 2
A getDockerImageSet() 0 4 1
A isUp() 0 3 1
A __construct() 0 10 1
A status() 0 3 1
A compose() 0 5 1
A logs() 0 3 1
A turnOnService() 0 12 3
A restartServing() 0 20 2
A build() 0 3 1
1
<?php
2
3
namespace App;
4
5
use App\Events\BuiltDockerCompose;
6
use App\Events\StartedPorter;
7
use App\Events\StartedPorterService;
8
use App\Events\StartingPorter;
9
use App\Events\StartingPorterService;
10
use App\Events\StoppedPorter;
11
use App\Events\StoppedPorterService;
12
use App\Events\StoppingPorter;
13
use App\Events\StoppingPorterService;
14
use App\Models\PhpVersion;
15
use App\Models\Setting;
16
use App\Support\Console\DockerCompose\CliCommandFactory;
17
use App\Support\Console\DockerCompose\YamlBuilder;
18
use App\Support\Contracts\Cli;
19
use App\Support\Contracts\ImageRepository;
20
use App\Support\Contracts\ImageSetRepository;
21
22
class Porter
23
{
24
    /**
25
     * The docker images sets used by Porter to serve sites.
26
     *
27
     * @var ImageSetRepository
28
     */
29
    protected $imageSets;
30
31
    /**
32
     * The CLI class that executes commands.
33
     *
34
     * @var Cli
35
     */
36
    protected $cli;
37
38
    /**
39
     * The Docker composer command factory.
40
     *
41
     * @var CliCommandFactory
42
     */
43
    protected $dockerCompose;
44
45
    /**
46
     * The DockerCompose YAML file builder.
47
     *
48
     * @var YamlBuilder
49
     */
50
    protected $yamlBuilder;
51
52
    /**
53
     * Porter constructor.
54
     *
55
     * @param ImageSetRepository $imageSets
56
     * @param Cli                $cli
57
     * @param CliCommandFactory  $commandFactory
58
     * @param YamlBuilder        $yamlBuilder
59
     */
60 191
    public function __construct(
61
        ImageSetRepository $imageSets,
62
        Cli $cli,
63
        CliCommandFactory $commandFactory,
64
        YamlBuilder $yamlBuilder
65
    ) {
66 191
        $this->imageSets = $imageSets;
67 191
        $this->cli = $cli;
68 191
        $this->dockerCompose = $commandFactory;
69 191
        $this->yamlBuilder = $yamlBuilder;
70 191
    }
71
72
    /**
73
     * Check if the Porter containers are running.
74
     *
75
     * @param string|null $service
76
     *
77
     * @return bool
78
     */
79 8
    public function isUp($service = null)
80
    {
81 8
        return (bool) stristr($this->dockerCompose->command('ps')->perform(), "porter_{$service}");
82
    }
83
84
    /**
85
     * Create the docker-compose.yaml file.
86
     */
87 7
    public function compose()
88
    {
89 7
        $filePath = $this->yamlBuilder->build($this->getDockerImageSet());
90
91 7
        event(new BuiltDockerCompose($filePath));
92 7
    }
93
94
    /**
95
     * Start Porter containers, optionally start a specific service, and force them to be recreated.
96
     *
97
     * @param string|null $service
98
     * @param bool        $recreate
99
     */
100 4
    public function start($service = null, $recreate = false)
101
    {
102 4
        $recreate = $recreate ? '--force-recreate ' : '';
103
104 4
        event(is_null($service) ? new StartingPorter() : new StartingPorterService($service));
105
106 4
        $this->dockerCompose->command("up -d {$recreate}--remove-orphans {$service}")->realTime()->perform();
107
108 4
        event(is_null($service) ? new StartedPorter() : new StartedPorterService($service));
109 4
    }
110
111
    /**
112
     * Stop Porter containers.
113
     *
114
     * @param string|null $service
115
     */
116 4
    public function stop($service = null)
117
    {
118 4
        event(is_null($service) ? new StoppingPorter() : new StoppingPorterService($service));
119
120 4
        if ($service) {
121 3
            $this->dockerCompose->command("stop {$service}")->realTime()->perform();
122 3
            event(new StoppedPorterService($service));
123
124 3
            return;
125
        }
126
127 1
        $this->dockerCompose->command('down --remove-orphans')->realTime()->perform();
128 1
        event(new StoppedPorter());
129 1
    }
130
131
    /**
132
     * Restart Porter containers.
133
     *
134
     * @param string|null $service
135
     */
136 2
    public function restart($service = null)
137
    {
138 2
        if ($this->isUp($service)) {
139
            $this->stop($service);
140
        }
141
142
        // If we're restarting something it's probably because config changed - so force recreation
143 2
        $this->start($service, true);
144 2
    }
145
146
    /**
147
     * Restart serving, picking up changes in used PHP versions and NGiNX.
148
     */
149 2
    public function restartServing()
150
    {
151
        // Build up docker-compose again - so we pick up any new PHP containers to be used
152 2
        $this->compose();
153
154 2
        if (!$this->isUp()) {
155 1
            return;
156
        }
157
158 1
        PhpVersion::active()
159 1
            ->get()
160
            ->reject(function ($phpVersion) {
161 1
                return $this->isUp($phpVersion->fpm_name);
162 1
            })
163
            ->each(function ($phpVersion) {
164 1
                $this->start($phpVersion->fpm_name);
165 1
                $this->start($phpVersion->cli_name);
166 1
            });
167
168 1
        $this->restart('nginx');
169 1
    }
170
171
    /**
172
     * Turn a service on.
173
     *
174
     * @param string $service
175
     */
176 2
    public function turnOnService($service)
177
    {
178 2
        if (setting("use_{$service}") == 'on') {
179 1
            return;
180
        }
181
182 1
        Setting::updateOrCreate("use_{$service}", 'on');
183
184 1
        $this->compose();
185
186 1
        if ($this->isUp()) {
187 1
            $this->start($service);
188
        }
189 1
    }
190
191
    /**
192
     * Turn a service off.
193
     *
194
     * @param string $service
195
     */
196 2
    public function turnOffService($service)
197
    {
198 2
        if (in_array(setting("use_{$service}"), [null, 'off'])) {
199 1
            return;
200
        }
201
202 1
        Setting::updateOrCreate("use_{$service}", 'off');
203
204 1
        if ($this->isUp()) {
205 1
            $this->stop($service);
206
        }
207 1
        $this->compose();
208 1
    }
209
210
    /**
211
     * (Re)build Porter containers.
212
     */
213 1
    public function build()
214
    {
215 1
        $this->dockerCompose->command('build')->perform();
216 1
    }
217
218
    /**
219
     * Get the current image set to use.
220
     *
221
     * @return ImageRepository
222
     */
223 7
    public function getDockerImageSet()
224
    {
225 7
        return $this->imageSets->getImageRepository(
226 7
            setting('docker_image_set', config('porter.default-docker-image-set'))
227
        );
228
    }
229
230
    /**
231
     * Show container status.
232
     */
233 1
    public function status()
234
    {
235 1
        echo $this->dockerCompose->command('ps')->perform();
236 1
    }
237
238
    /**
239
     * Show container logs.
240
     *
241
     * @param string|null $service
242
     */
243 1
    public function logs($service = null)
244
    {
245 1
        echo $this->dockerCompose->command("logs {$service}")->perform();
246 1
    }
247
}
248