Passed
Push — master ( caf93d...cf5135 )
by Keoghan
06:09
created

Porter   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 235
Duplicated Lines 0 %

Test Coverage

Coverage 98.67%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 25
eloc 55
c 4
b 0
f 0
dl 0
loc 235
ccs 74
cts 75
cp 0.9867
rs 10

14 Methods

Rating   Name   Duplication   Size   Complexity  
A start() 0 9 4
A stop() 0 13 3
A restart() 0 8 2
A isUp() 0 3 1
A __construct() 0 10 1
A compose() 0 5 1
A turnOffService() 0 12 3
A getDockerImageSet() 0 4 1
A softRestart() 0 3 1
A status() 0 3 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 206
    public function __construct(
61
        ImageSetRepository $imageSets,
62
        Cli $cli,
63
        CliCommandFactory $commandFactory,
64
        YamlBuilder $yamlBuilder
65
    ) {
66 206
        $this->imageSets = $imageSets;
67 206
        $this->cli = $cli;
68 206
        $this->dockerCompose = $commandFactory;
69 206
        $this->yamlBuilder = $yamlBuilder;
70 206
    }
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
     * Soft restart Porter containers.
148
     * Restart without getting config changes.
149
     *
150
     * @param string|null $service
151
     */
152 1
    public function softRestart($service = null)
153
    {
154 1
        $this->dockerCompose->command("restart {$service}")->realTime()->perform();
155 1
    }
156
157
    /**
158
     * Restart serving, picking up changes in used PHP versions and NGiNX.
159
     */
160 2
    public function restartServing()
161
    {
162
        // Build up docker-compose again - so we pick up any new PHP containers to be used
163 2
        $this->compose();
164
165 2
        if (!$this->isUp()) {
166 1
            return;
167
        }
168
169 1
        PhpVersion::active()
170 1
            ->get()
171
            ->reject(function ($phpVersion) {
172 1
                return $this->isUp($phpVersion->fpm_name);
173 1
            })
174
            ->each(function ($phpVersion) {
175 1
                $this->start($phpVersion->fpm_name);
176 1
                $this->start($phpVersion->cli_name);
177 1
            });
178
179 1
        $this->restart('nginx');
180 1
    }
181
182
    /**
183
     * Turn a service on.
184
     *
185
     * @param string $service
186
     */
187 2
    public function turnOnService($service)
188
    {
189 2
        if (setting("use_{$service}") == 'on') {
190 1
            return;
191
        }
192
193 1
        Setting::updateOrCreate("use_{$service}", 'on');
194
195 1
        $this->compose();
196
197 1
        if ($this->isUp()) {
198 1
            $this->start($service);
199
        }
200 1
    }
201
202
    /**
203
     * Turn a service off.
204
     *
205
     * @param string $service
206
     */
207 2
    public function turnOffService($service)
208
    {
209 2
        if (in_array(setting("use_{$service}"), [null, 'off'])) {
210 1
            return;
211
        }
212
213 1
        Setting::updateOrCreate("use_{$service}", 'off');
214
215 1
        if ($this->isUp()) {
216 1
            $this->stop($service);
217
        }
218 1
        $this->compose();
219 1
    }
220
221
    /**
222
     * (Re)build Porter containers.
223
     */
224 1
    public function build()
225
    {
226 1
        $this->dockerCompose->command('build')->perform();
227 1
    }
228
229
    /**
230
     * Get the current image set to use.
231
     *
232
     * @return ImageRepository
233
     */
234 7
    public function getDockerImageSet()
235
    {
236 7
        return $this->imageSets->getImageRepository(
237 7
            setting('docker_image_set', config('porter.default-docker-image-set'))
238
        );
239
    }
240
241
    /**
242
     * Show container status.
243
     */
244 1
    public function status()
245
    {
246 1
        echo $this->dockerCompose->command('ps')->perform();
247 1
    }
248
249
    /**
250
     * Show container logs.
251
     *
252
     * @param string|null $service
253
     */
254 1
    public function logs($service = null)
255
    {
256 1
        echo $this->dockerCompose->command("logs {$service}")->perform();
257 1
    }
258
}
259